def test_genrequest_default(self): """ Create a request only using the Communication-object """ config = get_config() if config.getboolean("genrequest_test", "enabled"): # Run only if enabled comm = Communication(config.get("genrequest_test", "url")) token = authenticate(config.get("genrequest_test", "url"), config.get("genrequest_test", "account"), config.get("genrequest_test", "preauthkey")) self.assertNotEqual(token, None, "Cannot authenticate.") request = comm.gen_request(token=token) request.add_request("NoOpRequest", {}, "urn:zimbraMail") response = comm.send_request(request) if response.is_fault(): self.fail( "Reponse failed: (%s) %s" % (response.get_fault_code(), response.get_fault_message()))
def test_fault_non_existing_folder_genrequest_xml(self): """ Request a non existing folder, so we get a fitting fault """ config = get_config() if config.getboolean('fault_test', 'enabled'): comm = Communication(config.get('fault_test', 'url')) token = auth.authenticate(config.get('fault_test', 'url'), config.get('fault_test', 'account'), config.get('fault_test', 'preauthkey'), config.get('fault_test', 'account_by')) request = comm.gen_request(request_type="xml", token=token) request.add_request( "GetFolderRequest", { "folder": { "path": config.get('fault_test', 'folder') } }, "urn:zimbraMail" ) response = comm.send_request(request) self.check_response( response )
def test_fault_non_existing_folder_genrequest_invalidurl(self): """ Request a non existing folder, so we get a fitting fault """ config = get_config() if config.getboolean('fault_test', 'enabled'): comm = Communication(config.get('fault_test', 'url') + "1234") token = auth.authenticate(config.get('fault_test', 'url'), config.get('fault_test', 'account'), config.get('fault_test', 'preauthkey'), config.get('fault_test', 'account_by')) request = comm.gen_request(token=token) request.add_request( "GetFolderRequest", { "folder": { "path": config.get('fault_test', 'folder') } }, "urn:zimbraMail" ) # A 404 error should by raised as an exception. self.assertRaises( Exception, comm.send_request, request )
def getDlData(name, url, token): comm = Communication(url) info_request = comm.gen_request(token=token) info_request.add_request('GetDistributionListRequest', {'dl': { '_content': name, 'by': 'name' }}, 'urn:zimbraAdmin') info_response = comm.send_request(info_request) data = {} data['members'] = [] if not info_response.is_fault(): zimbra_data = info_response.get_response( )['GetDistributionListResponse'] data['settings'] = dict.zimbra_to_python(zimbra_data['dl']['a'], key_attribute='n', content_attribute='_content') if 'dlm' in zimbra_data['dl']: for i in zimbra_data['dl']['dlm']: data['members'].append(i['_content']) data['id'] = zimbra_data['dl']['id'] data['name'] = zimbra_data['dl']['name'] return data else: print(info_response.get_fault_message()) sys.exit(1)
def __init__(self, server_host, server_port, *args, **kwargs): loc = 'https://%s:%s/%s' % (server_host, server_port, self.LOCATION) self.com = Communication(loc) self._server_host = server_host self._server_port = server_port self._session = ZimbraAPISession(self)
def run_request(self, creds, req, req_args={}): token = self.get_token( creds['url'], creds['user'], creds['pwd'], creds['admin_auth']) comm = Communication(creds['url']) zmreq = comm.gen_request(token=token, request_type="xml") zmreq.add_request(req, req_args, creds['urn']) resp = comm.send_request(zmreq) if resp.is_fault(): print(resp.get_fault_code()) ret = resp.get_response() return json.loads(ret['response']['content'])
def connect(self): url = os.environ['ZIMBRA_URL'] account = os.environ['ZIMBRA_ACCOUNT'] password = os.environ['ZIMBRA_PASSWORD'] try: self.comm = Communication(url) self.token = auth.authenticate(url, account, password, admin_auth=True) except: log.exception("locals=%s", locals()) if not self.token: raise Exception("Authentication failed: locals=%s", locals())
def connect(self): try: self.comm = Communication(self.url) self.__token = auth.authenticate(self.url, self.usr, self.__password, admin_auth=True) self.request = self.comm.gen_request(token=self.__token, set_batch=True) return 'Conectado' except urllib.error.URLError as E: # catastrophic error. bail. return f'Erro na conexão: {E}'
def test_autoresponse_xml(self): """ Create an XML-request and pass this to send_request expection a xml response. """ config = get_config() if config.getboolean("autoresponse_test", "enabled"): # Run only if enabled token = authenticate( config.get("autoresponse_test", "url"), config.get("autoresponse_test", "account"), config.get("autoresponse_test", "preauthkey") ) self.assertNotEqual( token, None, "Cannot authenticate." ) request = RequestXml() request.set_auth_token(token) request.add_request( "NoOpRequest", { }, "urn:zimbraMail" ) comm = Communication(config.get("autoresponse_test", "url")) response = comm.send_request(request) if response.is_fault(): self.fail( "Reponse failed: (%s) %s" % ( response.get_fault_code(), response.get_fault_message() ) ) self.assertEqual( response.response_type, "xml", "Invalid response type %s" % response.response_type )
def test_genrequest_check_response_xml(self): """ Create a request only using the Communication-object, send it and check the response """ config = get_config() if config.getboolean("genrequest_test", "enabled"): # Run only if enabled comm = Communication(config.get("genrequest_test", "url")) token = authenticate( config.get("genrequest_test", "url"), config.get("genrequest_test", "account"), config.get("genrequest_test", "preauthkey") ) self.assertNotEqual( token, None, "Cannot authenticate." ) request = comm.gen_request(request_type="xml", token=token) request.add_request( "GetInfoRequest", { }, "urn:zimbraAccount" ) response = comm.send_request(request) if response.is_fault(): self.fail( "Reponse failed: (%s) %s" % ( response.get_fault_code(), response.get_fault_message() ) ) self.assertEqual( response.get_response()["GetInfoResponse"]["name"], config.get("genrequest_test", "account"), "Request returned unexpected response" )
def test_genrequest_fail(self): """ Create a request only using the Communication-object """ config = get_config() if config.getboolean("genrequest_test", "enabled"): # Run only if enabled comm = Communication(config.get("genrequest_test", "url")) token = authenticate( config.get("genrequest_test", "url"), config.get("genrequest_test", "account"), config.get("genrequest_test", "preauthkey") ) self.assertNotEqual( token, None, "Cannot authenticate." ) self.assertRaises( UnknownRequestType, comm.gen_request, request_type="INVALID", token=token ) request = comm.gen_request(token=token) request.add_request( "NoOpRequest", { }, "urn:zimbraMail" ) # Deliberately break the request request.request_type = "INVALID" self.assertRaises( UnknownRequestType, comm.send_request, request )
def test_fault_non_existing_folder_batch_json(self): """ Request a non existing folder multiple times to get multiple faults """ config = get_config() if config.getboolean('fault_test', 'enabled'): comm = Communication(config.get('fault_test', 'url')) token = auth.authenticate(config.get('fault_test', 'url'), config.get('fault_test', 'account'), config.get('fault_test', 'preauthkey'), config.get('fault_test', 'account_by')) request = RequestJson() request.set_auth_token(token) request.enable_batch() request.add_request( "GetFolderRequest", { "folder": { "path": config.get('fault_test', 'folder') } }, "urn:zimbraMail" ) request.add_request( "GetFolderRequest", { "folder": { "path": config.get('fault_test', 'folder') } }, "urn:zimbraMail" ) response = ResponseJson() comm.send_request(request, response) self.check_response( response )
def __init__(self, admin_url, admin_user, admin_pass): self.admin_url = admin_url self.admin_user = admin_user self.admin_pass = admin_pass self.admin_account_by = 'name' self.request = None self.token = authenticate(self.admin_url, self.admin_user, self.admin_pass, self.admin_account_by, admin_auth=True, request_type="json") self.comm = Communication(self.admin_url)
def delMembers(dlId, member, url, token): if options.verbose: print('deleting member: ', member) comm = Communication(url) info_request = comm.gen_request(token=token) info_request.add_request('RemoveDistributionListMemberRequest', { 'id': dlId, 'dlm': { '_content': member } }, 'urn:zimbraAdmin') info_response = comm.send_request(info_request) if not info_response.is_fault(): zimbra_data = info_response.get_response( )['RemoveDistributionListMemberResponse'] else: print(info_response.get_fault_message()) sys.exit(1)
def __init__( self , cfg ): """ Initialise l'accès à l'API en lisant les paramètres de connexion dans la configuration et en créant l'instance de communication. """ self.url_ = cfg.get( 'bss' , 'zimbra-url' , 'https://webmail.partage.renater.fr/service/soap' ) self.domain_ = cfg.get( 'bss' , 'domain' ) self.dkey_ = cfg.get( 'bss' , 'token' ) self.fake_it_ = cfg.has_flag( 'bss' , 'simulate' ) self.user_ = None self.token_ = None # On lit le timeout depuis la configuration, s'il est défini. Sinon, # on utilise 10s par défaut. timeout_cfg = cfg.get( 'bss' , 'zimbra-timeout' , '10' ) try: timeout_cfg = int( timeout_cfg ) except ValueError as e: Logging( 'zimbra' ).error( 'Paramètre zimbra-timeout invalide' ) raise FatalError( 'Erreur de configuration' , e ) from pythonzimbra.communication import Communication self.comm_ = Communication( self.url_ , timeout = timeout_cfg )
def authenticate(url, account, key, by='name', expires=0, timestamp=None, timeout=None, request_type="xml", admin_auth=False, use_password=False, raise_on_error=False): """ Authenticate to the Zimbra server :param url: URL of Zimbra SOAP service :param account: The account to be authenticated against :param key: The preauth key of the domain of the account or a password (if admin_auth or use_password is True) :param by: If the account is specified as a name, an ID or a ForeignPrincipal :param expires: When the token expires (or 0 for default expiration) :param timestamp: When the token was requested (None for "now") :param timeout: Timeout for the communication with the server. Defaults to the urllib2-default :param request_type: Which type of request to use ("xml" (default) or "json") :param admin_auth: This request should authenticate and generate an admin token. The "key"-parameter therefore holds the admin password (implies use_password) :param use_password: The "key"-parameter holds a password. Do a password- based user authentication. :param raise_on_error: Should I raise an exception when an authentication error occurs or just return None? :return: The authentication token or None :rtype: str or None or unicode """ if timestamp is None: timestamp = int(time.time()) * 1000 pak = "" if not admin_auth: pak = preauth.create_preauth(account, key, by, expires, timestamp) if request_type == 'xml': auth_request = RequestXml() else: auth_request = RequestJson() request_data = {'account': {'by': by, '_content': account}} ns = "urn:zimbraAccount" if admin_auth: ns = "urn:zimbraAdmin" request_data['password'] = key elif use_password: request_data['password'] = {"_content": key} else: request_data['preauth'] = { 'timestamp': timestamp, 'expires': expires, '_content': pak } auth_request.add_request('AuthRequest', request_data, ns) server = Communication(url, timeout) if request_type == 'xml': response = ResponseXml() else: response = ResponseJson() server.send_request(auth_request, response) if response.is_fault(): if raise_on_error: raise AuthenticationFailed( "Cannot authenticate user: (%s) %s" % (response.get_fault_code(), response.get_fault_message())) return None return response.get_response()['AuthResponse']['authToken']['_content']
def _get_scope(self): """ Build up a list of users for the specified scope """ self.app.log.debug("Building up user list of scope definition") if self.app.pargs.scope == "": # Set the scope to the admin user's domain (local_part, domain_part) = self.app.pargs.user.split("@") scope_config = "DOMAIN=%s" % domain_part else: scope_config = self.app.pargs.scope (scope, scope_value) = scope_config.split("=") if scope not in ("DOMAIN", "LIST", "USER"): self.app.log.fatal("Scope not correctly configured. Please use " "DOMAIN, LIST or USER") exit(1) userlist = [] if scope == "DOMAIN": # Fetch all users in a domain self.app.log.debug( "Searching for accounts in domain %s" % scope_value ) comm = Communication(self.url) search_account_request = comm.gen_request(token=self.token) search_account_request.add_request( "SearchAccountsRequest", { "query": "", "domain": scope_value }, "urn:zimbraAdmin" ) search_account_response = comm.send_request(search_account_request) if search_account_response.is_fault(): self.app.log.fatal( "Cannot search for accounts in the specified domain %s: " "(%s) %s" % ( scope_value, search_account_response.get_fault_code(), search_account_response.get_fault_message() ) ) for account in search_account_response.get_response()[ "SearchAccountsResponse"]["account"]: userlist.append(account["name"]) elif scope == "LIST": # Fetch all users in a distribution list self.app.log.debug( "Searching for users in distribution list %s" % scope_value ) comm = Communication(self.url) get_distributionlist_request = comm.gen_request(token=self.token) get_distributionlist_request.add_request( "GetDistributionListRequest", { "dl": { "by": "name", "_content": scope_value } }, "urn:zimbraAdmin" ) get_distributionlist_response = comm.send_request( get_distributionlist_request ) if get_distributionlist_response.is_fault(): self.app.log.fatal( "Cannot search for accounts in the specified list %s: " "(%s) %s" % ( scope_value, get_distributionlist_response.get_fault_code(), get_distributionlist_response.get_fault_message() ) ) for member in get_distributionlist_response.get_response()[ "GetDistributionListResponse"]["dl"]["dlm"]: if type(member) == dict: userlist.append(member["_content"]) else: userlist.append(member) elif scope == "USER": # Just a single user userlist.append(scope_value) self.app.log.debug("Found these users:\n %s" % userlist) return userlist
def _get_devices(self, user): self.app.log.debug("Fetching devices of user %s" % user) (local_part, domain_part) = user.split("@") if domain_part not in self.preauth_cache: # No preauth key cached. Fetch one self.app.log.debug("Fetch preauth key for domain %s" % domain_part) comm = Communication(self.url) preauthkey_request = comm.gen_request(token=self.token) preauthkey_request.add_request( "GetDomainRequest", { "domain": { "by": "name", "_content": domain_part } }, "urn:zimbraAdmin" ) preauthkey_response = comm.send_request(preauthkey_request) if preauthkey_response.is_fault(): self.app.log.fatal( "Cannot fetch preauth key for domain %s" % domain_part, preauthkey_response.get_fault_code(), preauthkey_response.get_fault_message(), ) exit(1) preauth = get_value( preauthkey_response.get_response()["GetDomainResponse"][ "domain"]["a"], "zimbraPreAuthKey" ) if preauth is None: self.app.log.fatal( "Domain %s has no preauthkey. Please use zmprov gdpak " "<domain> first." % domain_part ) exit(1) self.preauth_cache[domain_part] = preauth else: preauth = self.preauth_cache[domain_part] user_token = auth.authenticate( self.user_url, user, preauth ) if user_token is None: self.app.log.fatal("Cannot login as user %s" % user) exit(1) user_comm = Communication(self.user_url) get_device_status_request = user_comm.gen_request(token=user_token) get_device_status_request.add_request( "GetDeviceStatusRequest", {}, "urn:zimbraSync" ) get_device_status_response = user_comm.send_request( get_device_status_request) if get_device_status_response.is_fault(): self.app.log.fatal( "Cannot fetch devices for user %s: (%s) %s" % ( user, get_device_status_response.get_fault_code(), get_device_status_response.get_fault_message() ) ) exit(1) devices = [] if "device" in get_device_status_response.get_response()[ "GetDeviceStatusResponse"]: devices = get_device_status_response.get_response()[ "GetDeviceStatusResponse"]["device"] if type(devices) == dict: devices = [devices] return devices
def test_genrequest_batch_invalid_xml(self): """ Create a batchrequest only using the Communication-object, send it and request an invalid request id (xml) """ config = get_config() if config.getboolean("genrequest_test", "enabled"): # Run only if enabled comm = Communication(config.get("genrequest_test", "url")) token = authenticate( config.get("genrequest_test", "url"), config.get("genrequest_test", "account"), config.get("genrequest_test", "preauthkey") ) self.assertNotEqual( token, None, "Cannot authenticate." ) request = comm.gen_request( request_type="xml", token=token, set_batch=True ) self.assertEqual( type(request), RequestXml, "Generated request wasn't an json-request, which should be " "the default." ) request.add_request( "NoOpRequest", { }, "urn:zimbraMail" ) request.add_request( "NoOpRequest", { }, "urn:zimbraMail" ) response = comm.send_request(request) if response.is_fault(): self.fail( "Reponse failed: (%s) %s" % ( response.get_fault_code(), response.get_fault_message() ) ) self.assertIsNone( response.get_response(3), "Querying an invalid requestId didn't return None" )
def test_genrequest_batch_xml(self): """ Create a batch-request only using the Communication-object ( xml-version) """ config = get_config() if config.getboolean("genrequest_test", "enabled"): # Run only if enabled comm = Communication(config.get("genrequest_test", "url")) token = authenticate( config.get("genrequest_test", "url"), config.get("genrequest_test", "account"), config.get("genrequest_test", "preauthkey") ) self.assertNotEqual( token, None, "Cannot authenticate." ) request = comm.gen_request( request_type="xml", token=token, set_batch=True ) self.assertEqual( type(request), RequestXml, "Generated request wasn't an xml-request" ) request.add_request( "NoOpRequest", { }, "urn:zimbraMail" ) request.add_request( "NoOpRequest", { }, "urn:zimbraMail" ) response = comm.send_request(request) if response.is_fault(): self.fail( "Reponse failed: (%s) %s" % ( response.get_fault_code(), response.get_fault_message() ) ) self.assertEqual( response.is_batch(), True, "Batch-request didn't return a Batch response." ) expected_batch = { 'nameToId': { 'NoOpResponse': [ '1', '2' ] }, 'hasFault': False, 'idToName': { '1': 'NoOpResponse', '2': 'NoOpResponse' } } self.assertEqual( response.get_batch(), expected_batch, "Batch-dictionary wasn't expected" )
def get_com(self): if self.comm is None: self.comm = Communication(self.url) return self.comm
help='webmail URL', required=True) parser.add_argument('-S', '--send-mail', dest='send_mail', nargs='+', metavar=('email', 'smtp-server'), help='Add this if you want to send output by email') argslist = parser.parse_args() url = "https://" + argslist.hostname + ":7071/service/admin/soap" admin = argslist.admin password = argslist.password domain = argslist.domain comm = Communication(url) sendm = argslist.send_mail def multipleReplace(text, wordDict): for key in wordDict: text = text.replace(key, wordDict[key]) return text def zimbraAttributes(): return [ 'displayName', 'description', 'zimbraAccountStatus', 'zimbraCOSId', 'zimbraLastLogonTimestamp' ]
def test_genrequest_check_response_batch_xml(self): """ Create a batch-request only using the Communication-object """ config = get_config() if config.getboolean("genrequest_test", "enabled"): # Run only if enabled comm = Communication(config.get("genrequest_test", "url")) token = authenticate( config.get("genrequest_test", "url"), config.get("genrequest_test", "account"), config.get("genrequest_test", "preauthkey") ) self.assertNotEqual( token, None, "Cannot authenticate." ) request = comm.gen_request( request_type="xml", token=token, set_batch=True ) self.assertEqual( type(request), RequestXml, "Generated request wasn't an json-request, which should be " "the default." ) request.add_request( "NoOpRequest", { }, "urn:zimbraMail" ) request.add_request( "GetInfoRequest", { }, "urn:zimbraAccount" ) response = comm.send_request(request) if response.is_fault(): self.fail( "Reponse failed: (%s) %s" % ( response.get_fault_code(), response.get_fault_message() ) ) self.assertEqual( response.get_response(2)["GetInfoResponse"]["name"], config.get("genrequest_test", "account"), "Request returned unexpected response" )
def run_admin_test(self, request_type): """ Actually do the work """ config = get_config() if config.getboolean("admin_request_test", "enabled"): # Run only if enabled token = authenticate(config.get("admin_request_test", "admin_url"), config.get("admin_request_test", "admin_account"), config.get("admin_request_test", "admin_password"), config.get("admin_request_test", "admin_account_by"), admin_auth=True, request_type=request_type) if token is None: self.fail("Authentication with the configured settings " "was not successful") # Create an account comm = Communication(config.get("admin_request_test", "admin_url")) if request_type == "xml": request = RequestXml() else: request = RequestJson() request.set_auth_token(token) request.add_request( "CreateAccountRequest", { "name": config.get("admin_request_test", "test_account"), "password": config.get("admin_request_test", "test_password") }, "urn:zimbraAdmin") if request_type == "xml": response = ResponseXml() else: response = ResponseJson() comm.send_request(request, response) if response.is_fault(): self.fail( "CreateAccount faulted. (%s) %s" % (response.get_fault_code(), response.get_fault_message())) account_id = response.get_response( )["CreateAccountResponse"]["account"]["id"] # Try to log in as the new account user_token = authenticate(config.get("admin_request_test", "url"), config.get("admin_request_test", "test_account"), config.get("admin_request_test", "test_password"), "name", request_type=request_type, use_password=True) if user_token is None: self.fail("Cannot log in as the test user.") # Remove account request.clean() response.clean() request.set_auth_token(token) request.add_request("DeleteAccountRequest", {"id": account_id}, "urn:zimbraAdmin") comm.send_request(request, response) if response.is_fault(): self.fail( "Cannot remove test account: (%s) %s" % (response.get_fault_code(), response.get_fault_message()))