def finalize_log(self): """ This method is used to log the data. It should hash the data and do a hash chain and sign the data """ try: self.audit_data["policies"] = ",".join(self.audit_data.get("policies",[])) if self.config.get("PI_AUDIT_SQL_TRUNCATE"): self._truncate_data() le = LogEntry(action=self.audit_data.get("action"), success=int(self.audit_data.get("success", 0)), serial=self.audit_data.get("serial"), token_type=self.audit_data.get("token_type"), user=self.audit_data.get("user"), realm=self.audit_data.get("realm"), resolver=self.audit_data.get("resolver"), administrator=self.audit_data.get("administrator"), action_detail=self.audit_data.get("action_detail"), info=self.audit_data.get("info"), privacyidea_server=self.audit_data.get("privacyidea_server"), client=self.audit_data.get("client", ""), loglevel=self.audit_data.get("log_level"), clearance_level=self.audit_data.get("clearance_level"), policies=self.audit_data.get("policies") ) self.session.add(le) self.session.commit() # Add the signature if self.sign_data and self.sign_object: s = self._log_to_string(le) sign = self.sign_object.sign(s) le.signature = sign self.session.merge(le) self.session.commit() except Exception as exx: # pragma: no cover # in case of a Unicode Error in _log_to_string() we won't have # a signature, but the log entry is available log.error("exception {0!r}".format(exx)) log.error("DATA: {0!s}".format(self.audit_data)) log.debug("{0!s}".format(traceback.format_exc())) self.session.rollback() finally: self.session.close() # clear the audit data self.audit_data = {}
def test_03_get_allowed_audit_realm(self): # Check than an internal admin is allowed to see all realms # A helpdesk user in "adminrealm" is only allowerd to see realm1A Audit(action="enroll", success=1, realm="realm1a").save() Audit(action="enroll", success=1, realm="realm1a").save() Audit(action="enroll", success=1, realm="realm2b").save() Audit(action="enroll", success=1, realm="realm2b").save() Audit(action="enroll", success=1, realm="realm2b").save() # check, that we see all audit entries with self.app.test_request_context('/audit/', method='GET', data={"realm": "realm1a"}, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = res.json self.assertTrue(json_response.get("result").get("status"), res) self.assertEqual( json_response.get("result").get("value").get("count"), 5) with self.app.test_request_context('/audit/', method='GET', data={"realm": "realm2b"}, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = res.json self.assertTrue(json_response.get("result").get("status"), res) self.assertEqual( json_response.get("result").get("value").get("count"), 7) # set policy: helpdesk users in adminrealm are only allowed to # view "realm1A". set_policy("audit01", scope=SCOPE.ADMIN, action=ACTION.AUDIT, adminrealm="adminrealm", realm="realm1a") # Test admin is allowed to view unrestricted logs! set_policy("audit02", scope=SCOPE.ADMIN, action=ACTION.AUDIT, user="******") rid = save_resolver({ "resolver": self.resolvername1, "type": "passwdresolver", "fileName": PWFILE }) self.assertTrue(rid > 0, rid) (added, failed) = set_realm("adminrealm", [self.resolvername1]) self.assertTrue(len(failed) == 0) self.assertTrue(len(added) == 1) helpdesk_authorization = None with self.app.test_request_context('/auth', method='POST', data={ 'username': '******', 'password': '******' }): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = res.json value = json_response.get("result").get("value") # Helpdesk user is allowed to view the audit log. self.assertTrue("auditlog" in value.get("rights")) helpdesk_authorization = value.get("token") # check, that we only see allowed audit realms with self.app.test_request_context( '/audit/', method='GET', headers={'Authorization': helpdesk_authorization}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = res.json self.assertTrue(json_response.get("result").get("status"), res) # We now have 3 entries, as we added one by the search in line #43 count = json_response.get("result").get("value").get("count") auditdata = json_response.get("result").get("value").get( "auditdata") self.assertEqual(count, 6) # All entries are in realm1A! for ad in auditdata: self.assertEqual(ad.get("realm"), "realm1a") # Now check, that the testadmin (self.at) sees all entries! with self.app.test_request_context('/audit/', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = res.json self.assertTrue(json_response.get("result").get("status"), res) # We now have 3 entries, as we added one by the search in line #43 count = json_response.get("result").get("value").get("count") auditdata = json_response.get("result").get("value").get( "auditdata") self.assertEqual(count, 20) # delete policy delete_policy("audit01") delete_policy("audit02")
def test_02_get_allowed_audit_realm(self): # Check that an administrator is only allowed to see log entries of # the defined realms. # fill some audit entries Audit(action="enroll", success=1, realm=self.realm1a).save() Audit(action="enroll", success=1, realm=self.realm1a).save() Audit(action="enroll", success=1, realm=self.realm2b).save() Audit(action="enroll", success=1, realm=self.realm2b).save() Audit(action="enroll", success=1, realm=self.realm2b).save() # check, that we see all audit entries with self.app.test_request_context('/audit/', method='GET', data={"realm": self.realm1a}, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = res.json self.assertTrue(json_response.get("result").get("status"), res) self.assertEqual( json_response.get("result").get("value").get("count"), 2) with self.app.test_request_context('/audit/', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = res.json self.assertTrue(json_response.get("result").get("status"), res) self.assertGreaterEqual( json_response.get("result").get("value").get("count"), 7) audit_list = json_response.get("result").get("value").get( "auditdata") audit_actions = [ a for a in audit_list if a.get("action") == "GET /audit/" ] self.assertGreaterEqual(len(audit_actions), 1) with self.app.test_request_context('/audit/', method='GET', data={"realm": self.realm2b}, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = res.json self.assertTrue(json_response.get("result").get("status"), res) self.assertEqual( json_response.get("result").get("value").get("count"), 3) # set policy for audit realms set_policy("audit01", scope=SCOPE.ADMIN, action=ACTION.AUDIT, realm=self.realm1a) # check, that we only see allowed audit realms with self.app.test_request_context('/audit/', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = res.json self.assertTrue(json_response.get("result").get("status"), res) # We now have 3 entries, as we added one by the search in line #43 audit_list = json_response.get("result").get("value").get( "auditdata") audit_realms = [ a for a in audit_list if a.get("realm") == self.realm1a ] self.assertEqual(len(audit_realms), 3) self.assertEqual( json_response.get("result").get("value").get("count"), 3) # delete policy delete_policy("audit01")
def test_04_get_user_audit_log(self): # Test that the user only sees audit log entries with his own data self.setUp_user_realms() # prepare some log entries for the normal user to try to fetch Audit(action="enroll", success=1, user="******", administrator=None, resolver="resolver1", realm=self.realm1a).save() Audit(action="enroll", success=1, user="******", administrator=None, resolver="resolver1", realm=self.realm1a).save() Audit(action="enroll", success=1, user="******", administrator=None, resolver="resolver1", realm=self.realm2b).save() Audit(action="enroll", success=1, user="******", administrator=None, resolver="resolver1", realm=self.realm2b).save() Audit(action="enroll", success=1, user="******", administrator=None, resolver="resolver1", realm=self.realm2b).save() # set policy: normal users in realm1a are allowed to view audit log set_policy("audit01", scope=SCOPE.USER, action=ACTION.AUDIT, realm=self.realm1a) user_authorization = None with self.app.test_request_context('/auth', method='POST', data={ 'username': '******'.format( self.realm1a), 'password': '******' }): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = res.json value = json_response.get("result").get("value") self.assertTrue("auditlog" in value.get("rights")) user_authorization = value.get("token") # check, that the normal user only sees his own entries with self.app.test_request_context( '/audit/', method='GET', data={ "action": "**", "action_detail": "**", "administrator": "**", "client": "**", "date": "**", "info": "**", "page": "1", "page_size": "10", "policies": "**", "privacyidea_server": "**", "realm": "**", "resolver": "**", "serial": "**", "sortorder": "desc", "success": "**", "tokentype": "**", "user": "******" }, headers={'Authorization': user_authorization}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = res.json self.assertTrue(json_response.get("result").get("status"), res) # We now have 3 entries, as we added one by the search in line #43 count = json_response.get("result").get("value").get("count") auditdata = json_response.get("result").get("value").get( "auditdata") self.assertGreaterEqual(count, 3) # All entries are in realm1A! for ad in auditdata: self.assertEqual(ad.get("realm"), self.realm1a) # try to explicitly query another realm with self.app.test_request_context( '/audit/', method='GET', data={ "action": "**", "action_detail": "**", "administrator": "**", "client": "**", "date": "**", "info": "**", "page": "1", "page_size": "10", "policies": "**", "privacyidea_server": "**", "realm": self.realm2b, "resolver": "**", "serial": "**", "sortorder": "desc", "success": "**", "tokentype": "**", "user": "******" }, headers={'Authorization': user_authorization}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) json_response = res.json self.assertTrue(json_response.get("result").get("status"), res) # The normal user can not fetch audit entries, that do not belong to him! count = json_response.get("result").get("value").get("count") self.assertGreaterEqual(count, 0) # delete policy delete_policy("audit01")
def finalize_log(self): """ This method is used to log the data. It should hash the data and do a hash chain and sign the data """ try: self.audit_data["policies"] = ",".join( self.audit_data.get("policies", [])) if self.config.get("PI_AUDIT_SQL_TRUNCATE"): self._truncate_data() if "tokentype" in self.audit_data: log.warning( "We have a wrong 'tokentype' key. This should not happen. Fix it!. " "Error occurs in action: {0!r}.".format( self.audit_data.get("action"))) if not "token_type" in self.audit_data: self.audit_data["token_type"] = self.audit_data.get( "tokentype") if self.audit_data.get("startdate"): duration = datetime.datetime.now() - self.audit_data.get( "startdate") else: duration = None le = LogEntry( action=self.audit_data.get("action"), success=int(self.audit_data.get("success", 0)), serial=self.audit_data.get("serial"), token_type=self.audit_data.get("token_type"), user=self.audit_data.get("user"), realm=self.audit_data.get("realm"), resolver=self.audit_data.get("resolver"), administrator=self.audit_data.get("administrator"), action_detail=self.audit_data.get("action_detail"), info=self.audit_data.get("info"), privacyidea_server=self.audit_data.get("privacyidea_server"), client=self.audit_data.get("client", ""), loglevel=self.audit_data.get("log_level"), clearance_level=self.audit_data.get("clearance_level"), policies=self.audit_data.get("policies"), startdate=self.audit_data.get("startdate"), duration=duration) self.session.add(le) self.session.commit() # Add the signature if self.sign_data and self.sign_object: s = self._log_to_string(le) sign = self.sign_object.sign(s) le.signature = sign self.session.merge(le) self.session.commit() except Exception as exx: # pragma: no cover # in case of a Unicode Error in _log_to_string() we won't have # a signature, but the log entry is available log.error("exception {0!r}".format(exx)) log.error("DATA: {0!s}".format(self.audit_data)) log.debug("{0!s}".format(traceback.format_exc())) self.session.rollback() finally: self.session.close() # clear the audit data self.audit_data = {}