def testDeleteHunt(self): # This needs to be created by a different user so we can test the # approval dialog. hunt = self.CreateSampleHunt( stopped=True, token=access_control.ACLToken(username="******", reason="test")) self.Open("/") self.WaitUntil(self.IsElementPresent, "client_query") self.Click("css=a[grrtarget=hunts]") self.WaitUntil(self.IsTextPresent, "GenericHunt") # Select a Hunt. self.Click("css=td:contains('GenericHunt')") # Click on delete button. self.Click("css=button[name=DeleteHunt]") self.WaitUntil(self.IsTextPresent, "Delete this hunt") # Click on Proceed. self.Click("css=button[name=Proceed]") # This should be rejected now and a form request is made. self.WaitUntil(self.IsTextPresent, "Create a new approval") self.Click("css=grr-request-approval-dialog button[name=Cancel]") # Wait for dialog to disappear. self.WaitUntilNot(self.IsVisible, "css=.modal-open") # Now create an approval. self.RequestAndGrantHuntApproval(hunt.session_id.Basename()) # Select a hunt again, as it's deselected after approval dialog # disappears. TODO(user): if this behavior is not convenient, fix it. self.Click("css=td:contains('GenericHunt')") # Click on Delete button and check that dialog appears. self.Click("css=button[name=DeleteHunt]") self.WaitUntil(self.IsTextPresent, "Delete this hunt") # Click on "Proceed" and wait for success label to appear. # Also check that "Proceed" button gets disabled. self.Click("css=button[name=Proceed]") self.WaitUntil(self.IsTextPresent, "Hunt deleted successfully!") self.assertFalse(self.IsElementPresent("css=button[name=Proceed]")) # Click on "Cancel" and check that dialog disappears. self.Click("css=button[name=Close]") self.WaitUntilNot(self.IsVisible, "css=.modal-open")
def main(argv): """Main.""" del argv # Unused. banner = ("\nWelcome to the GRR console\n") config.CONFIG.AddContext(contexts.COMMAND_LINE_CONTEXT) config.CONFIG.AddContext( contexts.CONSOLE_CONTEXT, "Context applied when running the console binary.") server_startup.Init() fleetspeak_connector.Init() # To make the console easier to use, we make a default token which will be # used in StartFlow operations. data_store.default_token = access_control.ACLToken( username=getpass.getuser(), reason=flags.FLAGS.reason) locals_vars = { "__name__": "GRR Console", "l": Lister, "lc": GetChildrenList, "o": aff4.FACTORY.Open, # Bring some symbols from other modules into the console's # namespace. "StartFlowAndWait": flow_utils.StartFlowAndWait, "StartFlowAndWorker": debugging.StartFlowAndWorker, } locals_vars.update(globals()) # add global variables to console if flags.FLAGS.client is not None: locals_vars["client"], locals_vars["token"] = console_utils.OpenClient( client_id=flags.FLAGS.client) if flags.FLAGS.code_to_execute: logging.info("Running code from flag: %s", flags.FLAGS.code_to_execute) exec(flags.FLAGS.code_to_execute) # pylint: disable=exec-used elif flags.FLAGS.command_file: logging.info("Running code from file: %s", flags.FLAGS.command_file) execfile(flags.FLAGS.command_file) if (flags.FLAGS.exit_on_complete and (flags.FLAGS.code_to_execute or flags.FLAGS.command_file)): return else: # We want the normal shell. locals_vars.update(globals()) # add global variables to console ipshell.IPShell(argv=[], user_ns=locals_vars, banner=banner)
def Run(self): with test_lib.FakeTime(42): self.CreateAdminUser("approver") clients = self.SetupClients(2) for client_id in clients: # Delete the certificate as it's being regenerated every time the # client is created. with aff4.FACTORY.Open(client_id, mode="rw", token=self.token) as grr_client: grr_client.DeleteAttribute(grr_client.Schema.CERT) with test_lib.FakeTime(44): approval_urn = security.ClientApprovalRequestor( reason=self.token.reason, subject_urn=clients[0], approver="approver", token=self.token).Request() approval1_id = approval_urn.Basename() with test_lib.FakeTime(45): approval_urn = security.ClientApprovalRequestor( reason=self.token.reason, subject_urn=clients[1], approver="approver", token=self.token).Request() approval2_id = approval_urn.Basename() with test_lib.FakeTime(84): approver_token = access_control.ACLToken(username="******") security.ClientApprovalGrantor(reason=self.token.reason, delegate=self.token.username, subject_urn=clients[1], token=approver_token).Grant() with test_lib.FakeTime(126): self.Check("ListClientApprovals", args=user_plugin.ApiListClientApprovalsArgs(), replace={ approval1_id: "approval:111111", approval2_id: "approval:222222" }) self.Check("ListClientApprovals", args=user_plugin.ApiListClientApprovalsArgs( client_id=clients[0].Basename()), replace={ approval1_id: "approval:111111", approval2_id: "approval:222222" })
def _LogFlowState(self, responses): session_id = responses[0].session_id token = access_control.ACLToken(username="******", reason="Logging") token.supervisor = True logging.error("No valid Status message.\nState:\n%s\n%s\n%s", data_store.DB.ResolvePrefix( session_id.Add("state"), "flow:", token=token), data_store.DB.ResolvePrefix( session_id.Add( "state/request:%08X" % responses[0].request_id), "flow:", token=token), data_store.DB.ResolvePrefix( queues.FLOWS, "notify:%s" % session_id, token=token))
def testSupervisorCanDoAnything(self): token = access_control.ACLToken(username="******", supervisor=True) self.assertTrue( self.access_manager.CheckClientAccess(token, "aff4:/C.0000000000000001")) self.assertTrue( self.access_manager.CheckHuntAccess(token, "aff4:/hunts/H:12344")) self.assertTrue( self.access_manager.CheckCronJobAccess(token, "aff4:/cron/blah")) self.assertTrue( self.access_manager.CheckIfCanStartFlow(token, "SomeFlow")) self.assertTrue( self.access_manager.CheckDataStoreAccess(token, ["aff4:/foo/bar"], requested_access="w"))
def testFiltersHuntsByCreator(self): for i in range(5): self.CreateHunt( description="foo_hunt_%d" % i, token=access_control.ACLToken(username="******")) for i in range(3): self.CreateHunt( description="bar_hunt_%d" % i, token=access_control.ACLToken(username="******")) result = self.handler.Handle( hunt_plugin.ApiListHuntsArgs(created_by="user-foo", active_within="1d"), token=self.token) self.assertEqual(len(result.items), 5) for item in result.items: self.assertEqual(item.creator, "user-foo") result = self.handler.Handle( hunt_plugin.ApiListHuntsArgs(created_by="user-bar", active_within="1d"), token=self.token) self.assertEqual(len(result.items), 3) for item in result.items: self.assertEqual(item.creator, "user-bar")
def testSetsSettingsForUserCorrespondingToToken(self): settings = aff4_users.GUISettings(mode="ADVANCED", canary_mode=True) user = user_plugin.ApiGrrUser(settings=settings) self.handler.Handle(user, token=access_control.ACLToken(username="******")) # Check that settings for user "foo" were applied. fd = aff4.FACTORY.Open("aff4:/users/foo", token=self.token) self.assertEqual(fd.Get(fd.Schema.GUI_SETTINGS), settings) # Check that settings were applied in relational db. u = data_store.REL_DB.ReadGRRUser("foo") self.assertEqual(settings.mode, u.ui_mode) self.assertEqual(settings.canary_mode, u.canary_mode)
def RequestAndGrantClientApproval(client_id, token=None, approver="approver", reason="testing"): token = token or GetToken() ApprovalRequest(client_id, token=token, approver=approver, reason=reason) user = aff4.FACTORY.Create( "aff4:/users/%s" % approver, users.GRRUser, token=token.SetUID()) user.Flush() approver_token = access_control.ACLToken(username=approver) security.ClientApprovalGrantor( reason=reason, delegate=token.username, subject_urn=rdf_client.ClientURN(client_id), token=approver_token).Grant()
def testEmptySubjectShouldRaise(self): token = access_control.ACLToken(username="******") with self.assertRaises(ValueError): self.access_manager.CheckClientAccess(token, "") with self.assertRaises(ValueError): self.access_manager.CheckHuntAccess(token, "") with self.assertRaises(ValueError): self.access_manager.CheckCronJobAccess(token, "") with self.assertRaises(ValueError): self.access_manager.CheckDataStoreAccess(token, [""], requested_access="r")
def LoadServerMapping(self): """Retrieve server mapping from database.""" # TODO(user): this SetUID can likely be replaced with a read ACL. token = access_control.ACLToken(username="******").SetUID() mapping_str, _ = self.db.Resolve( MAP_SUBJECT, MAP_VALUE_PREDICATE, token=token) if not mapping_str: return None mapping = rdf_data_server.DataServerMapping.FromSerializedString( mapping_str) # Restore pathing information. if self._DifferentPathing(list(mapping.pathing)): self.pathing = list(mapping.pathing) self.db.RecreatePathing(self.pathing) return mapping
def testRendersSettingsForUserCorrespondingToToken(self): with aff4.FACTORY.Create(aff4.ROOT_URN.Add("users").Add("foo"), aff4_type=aff4_users.GRRUser, mode="w", token=self.token) as user_fd: user_fd.Set( user_fd.Schema.GUI_SETTINGS, aff4_users.GUISettings( mode="ADVANCED", canary_mode=True, )) result = self.handler.Handle( None, token=access_control.ACLToken(username="******")) self.assertEqual(result.settings.mode, "ADVANCED") self.assertEqual(result.settings.canary_mode, True)
def __init__(self, methodName=None): # pylint: disable=g-bad-name """Hack around unittest's stupid constructor. We sometimes need to instantiate the test suite without running any tests - e.g. to start initialization or setUp() functions. The unittest constructor requires to provide a valid method name. Args: methodName: The test method to run. """ super(GRRBaseTest, self).__init__(methodName=methodName or "__init__") self.base_path = config.CONFIG["Test.data_dir"] test_user = "******" users.GRRUser.SYSTEM_USERS.add(test_user) self.token = access_control.ACLToken(username=test_user, reason="Running tests")
def SaveServerMapping(self, mapping, create_pathing=False): """Stores the server mapping in the data store.""" if create_pathing: # We are going to use our own pathing. mapping.pathing = self.pathing else: # We are going to use the mapping pathing configuration. # Check if its different than the one we use now and then ask the # datastore to use it. new_pathing = list(mapping.pathing) if self._DifferentPathing(new_pathing): self.pathing = new_pathing self.db.RecreatePathing(new_pathing) # SetUID is required to write to aff4:/servers_map token = access_control.ACLToken(username="******").SetUID() self.db.MultiSet(MAP_SUBJECT, {MAP_VALUE_PREDICATE: mapping}, token=token)
def StartFlowAndWorker(client_id, flow_name, **kwargs): """Launches the flow and worker and waits for it to finish. Args: client_id: The client common name we issue the request. flow_name: The name of the flow to launch. **kwargs: passthrough to flow. Returns: A flow session id. Note: you need raw access to run this flow as it requires running a worker. """ # Empty token, only works with raw access. queue = rdfvalue.RDFURN("DEBUG-%s-" % getpass.getuser()) if "token" in kwargs: token = kwargs.pop("token") else: token = access_control.ACLToken(username="******") session_id = flow.GRRFlow.StartFlow(client_id=client_id, flow_name=flow_name, queue=queue, token=token, **kwargs) worker_thrd = worker.GRRWorker(queues=[queue], token=token, threadpool_size=1) while True: try: worker_thrd.RunOnce() except KeyboardInterrupt: print "exiting" worker_thrd.thread_pool.Join() break time.sleep(2) with aff4.FACTORY.Open(session_id, token=token) as flow_obj: if not flow_obj.GetRunner().IsRunning(): break # Terminate the worker threads worker_thrd.thread_pool.Join() return session_id
def RequestCronJobApproval(self, cron_job_id, requestor=None, reason=None, approver="approver"): """Request cron job approval for a given cron job.""" if not requestor: requestor = self.token.username if not reason: reason = self.token.reason requestor = security.CronJobApprovalRequestor( subject_urn=rdfvalue.RDFURN("cron").Add(cron_job_id), reason=reason, approver=approver, token=access_control.ACLToken(username=requestor)) return requestor.Request().Basename()
def CreateFileVersions(self, client_id, file_path): """Add a new version for a file.""" with test_lib.FakeTime(self.time_1): token = access_control.ACLToken(username="******") fd = aff4.FACTORY.Create(client_id.Add(file_path), aff4.AFF4MemoryStream, mode="w", token=token) fd.Write("Hello World") fd.Close() with test_lib.FakeTime(self.time_2): fd = aff4.FACTORY.Create(client_id.Add(file_path), aff4.AFF4MemoryStream, mode="w", token=token) fd.Write("Goodbye World") fd.Close()
def GrantCronJobApproval(self, cron_job_id, requestor=None, reason=None, approver="approver"): """Grants an approval for a given cron job.""" if not requestor: requestor = self.token.username if not reason: reason = self.token.reason self.CreateAdminUser(approver) approver_token = access_control.ACLToken(username=approver) security.CronJobApprovalGrantor( subject_urn=rdfvalue.RDFURN("cron").Add(cron_job_id), reason=reason, delegate=requestor, token=approver_token).Grant()
def UpdateLoop(self): token = access_control.ACLToken(username="******", reason="Updating An Index") while not self.exit_now: with self.cv: while not self.to_process: self.cv.wait() next_update = self.to_process.popleft() if next_update is None: return now = time.time() next_cls = next_update[0] next_urn = next_update[1] next_time = next_update[2] while now < next_time: time.sleep(next_time - now) now = time.time() self.ProcessCollection(next_cls, next_urn, token)
def RequestHuntApproval(self, hunt_id, requestor=None, reason=None, approver="approver"): """Request hunt approval for a given hunt.""" if not requestor: requestor = self.token.username if not reason: reason = self.token.reason token = access_control.ACLToken(username=requestor) requestor = security.HuntApprovalRequestor( subject_urn=rdfvalue.RDFURN("hunts").Add(hunt_id), reason=reason, approver=approver, token=token) return requestor.Request().Basename()
def __init__(self, certificate, private_key, max_queue_size=50, message_expiry_time=120, max_retransmission_time=10, threadpool_prefix="grr_threadpool"): # Identify ourselves as the server. self.token = access_control.ACLToken(username="******", reason="Implied.") self.token.supervisor = True if data_store.RelationalDBReadEnabled(): self._communicator = RelationalServerCommunicator( certificate=certificate, private_key=private_key) else: self._communicator = ServerCommunicator(certificate=certificate, private_key=private_key, token=self.token) self.receive_thread_pool = {} self.message_expiry_time = message_expiry_time self.max_retransmission_time = max_retransmission_time self.max_queue_size = max_queue_size self.thread_pool = threadpool.ThreadPool.Factory( threadpool_prefix, min_threads=2, max_threads=config.CONFIG["Threadpool.size"]) self.thread_pool.Start() # Well known flows are run on the front end. self.well_known_flows = (flow.WellKnownFlow.GetAllWellKnownFlows( token=self.token)) well_known_flow_names = self.well_known_flows.keys() for well_known_flow in well_known_flow_names: if well_known_flow not in config.CONFIG[ "Frontend.well_known_flows"]: del self.well_known_flows[well_known_flow] self.well_known_flows_blacklist = set( config.CONFIG["Frontend.DEBUG_well_known_flows_blacklist"])
def CheckClientApprovalRequest(approval_request): """Checks if a client approval request is granted.""" _CheckExpired(approval_request) _CheckHasEnoughGrants(approval_request) if not client_approval_auth.CLIENT_APPROVAL_AUTH_MGR.IsActive(): return True token = access_control.ACLToken(username=approval_request.requestor_username) approvers = set(g.grantor_username for g in approval_request.grants) labels = sorted( data_store.REL_DB.ReadClientLabels(approval_request.subject_id), key=lambda l: l.name) for label in labels: client_approval_auth.CLIENT_APPROVAL_AUTH_MGR.CheckApproversForLabel( token, rdfvalue.RDFURN(approval_request.subject_id), approval_request.requestor_username, approvers, label.name) return True
def testShows5LatestHunts(self): # Only hunts created in the last 31 days will get shown, so we have # to adjust their timestamps accordingly. timestamp = rdfvalue.RDFDatetime.Now() - rdfvalue.Duration("1d") for i in range(20): with test_lib.FakeTime(timestamp + rdfvalue.Duration(1000 * i)): if i % 2 == 0: descr = "foo-%d" % i token = access_control.ACLToken(username="******") else: descr = "bar-%d" % i token = self.token self.CreateSampleHunt(descr, token=token) self.Open("/") for i in range(11, 20, 2): self.WaitUntil(self.IsElementPresent, "css=grr-user-dashboard " "div[name=RecentlyCreatedHunts]:contains('bar-%d')" % i) self.WaitUntilNot(self.IsElementPresent, "css=grr-user-dashboard " "div[name=RecentlyCreatedHunts]:contains('foo')")
def RunOnce(self): """Initializes StatsStore and StatsStoreWorker.""" # SetUID is required to create and write to aff4:/stats_store token = access_control.ACLToken(username="******").SetUID() global STATS_STORE STATS_STORE = aff4.FACTORY.Create(None, StatsStore, mode="w", token=token) try: STATS_STORE.Flush() except access_control.UnauthorizedAccess: logging.info("Not writing aff4:/stats_store due to lack of permissions.") # We don't need StatsStoreWorker if there's no StatsStore.process_id in # the config. stats_process_id = config.CONFIG["StatsStore.process_id"] if not stats_process_id: return stats_store_worker = StatsStoreWorker(STATS_STORE, stats_process_id) stats_store_worker.RunAsync()
def GrantClientApproval(self, client_id, requestor=None, approval_id=None, approver="approver", admin=True): """Grant an approval from approver to delegate. Args: client_id: ClientURN requestor: username string of the user receiving approval. approval_id: id of the approval to grant. approver: username string of the user granting approval. admin: If True, make approver an admin user. Raises: ValueError: if approval_id is empty. """ if not approval_id: raise ValueError("approval_id can't be empty.") if hasattr(client_id, "Basename"): client_id = client_id.Basename() if not requestor: requestor = self.token.username self.CreateUser(requestor) if admin: self.CreateAdminUser(approver) else: self.CreateUser(approver) if not requestor: requestor = self.token.username args = api_user.ApiGrantClientApprovalArgs(client_id=client_id, username=requestor, approval_id=approval_id) handler = api_user.ApiGrantClientApprovalHandler() handler.Handle(args, token=access_control.ACLToken(username=approver))
def testCreatorPropagation(self): # Instantiate the flow using one username. session_id = flow.GRRFlow.StartFlow( client_id=self.client_id, flow_name="ParentFlow", sync=False, token=access_control.ACLToken( username="******", reason="testing")) # Run the flow using another user ("test"). for _ in flow_test_lib.TestFlowHelper( session_id, ClientMock(), client_id=self.client_id, token=self.token): pass self.assertEqual(ParentFlow.success, True) subflows = list( obj for obj in aff4.FACTORY.Open(session_id, token=self.token) .OpenChildren() if isinstance(obj, flow.GRRFlow)) self.assertEqual(len(subflows), 1) self.assertEqual(subflows[0].GetRunner().context.creator, "original_user")
def RequestClientApproval(self, client_id, reason=None, requestor=None, email_cc_address=None, approver="approver"): """Create an approval request to be sent to approver.""" if hasattr(client_id, "Basename"): client_id = client_id.Basename() if not requestor: requestor = self.token.username if not reason: reason = self.token.reason requestor = security.ClientApprovalRequestor( subject_urn=client_id, reason=reason, approver=approver, email_cc_address=email_cc_address, token=access_control.ACLToken(username=requestor)) return requestor.Request().Basename()
def CreateHuntFixtureWithTwoClients(): token = access_control.ACLToken(username="******", reason="test") # Ensure that clients list is empty root = aff4.FACTORY.Open(aff4.ROOT_URN, token=token) for client_urn in root.ListChildren(): if aff4_grr.VFSGRRClient.CLIENT_ID_RE.match(client_urn.Basename()): data_store.DB.DeleteSubject(client_urn) # Add 2 distinct clients client_id = "C.1%015d" % 0 fd = aff4.FACTORY.Create( rdf_client.ClientURN(client_id), aff4_grr.VFSGRRClient, token=token) fd.Set(fd.Schema.SYSTEM("Windows")) fd.Set(fd.Schema.CLOCK(2336650631137737)) fd.Close() client_id = "C.1%015d" % 1 fd = aff4.FACTORY.Create( rdf_client.ClientURN(client_id), aff4_grr.VFSGRRClient, token=token) fd.Set(fd.Schema.SYSTEM("Linux")) fd.Set(fd.Schema.CLOCK(2336650631137737)) fd.Close()
def ApprovalRevokeRaw(aff4_path, token): """Revokes an approval for a given token. This method requires raw datastore access to manipulate approvals directly. Args: aff4_path: The aff4_path or client id the approval should be created for. token: The token that should be revoked. """ try: urn = rdf_client.ClientURN(aff4_path) except type_info.TypeValueError: urn = rdfvalue.RDFURN(aff4_path) approval_urn = aff4.ROOT_URN.Add("ACL").Add(urn.Path()).Add( token.username).Add(utils.EncodeReasonString(token.reason)) super_token = access_control.ACLToken(username="******") super_token.supervisor = True approval_request = aff4.FACTORY.Open( approval_urn, mode="rw", token=super_token) approval_request.DeleteAttribute(approval_request.Schema.APPROVER) approval_request.Close()
def testIncludesApproversInResultWhenApprovalIsGranted(self): approval_urn = aff4_security.ClientApprovalRequestor( reason="blah", subject_urn=self.client_id, approver="approver", token=self.token).Request() approval_id = approval_urn.Basename() approver_token = access_control.ACLToken(username="******") aff4_security.ClientApprovalGrantor(reason="blah", delegate=self.token.username, subject_urn=self.client_id, token=approver_token).Grant() args = user_plugin.ApiGetClientApprovalArgs( client_id=self.client_id, approval_id=approval_id, username=self.token.username) result = self.handler.Handle(args, token=self.token) self.assertTrue(result.is_valid) self.assertEqual( sorted(result.approvers), sorted([approver_token.username, self.token.username]))
def SecurityCheck(self, func, request, *args, **kwargs): """Wrapping function.""" request.user = "" authorized = False try: auth_type, authorization = request.headers.get( "Authorization", " ").split(" ", 1) if auth_type == "Basic": user, password = authorization.decode("base64").split(":", 1) token = access_control.ACLToken(username=user) fd = aff4.FACTORY.Open("aff4:/users/%s" % user, aff4_type=aff4_users.GRRUser, token=token) crypted_password = fd.Get(fd.Schema.PASSWORD) if crypted_password and crypted_password.CheckPassword( password): authorized = True # The password is ok - update the user request.user = user except (IndexError, KeyError, IOError, access_control.UnauthorizedAccess): pass if not authorized: result = werkzeug_wrappers.Response("Unauthorized", status=401) result.headers["WWW-Authenticate"] = "Basic realm='Secure Area'" return result # Modify this to implement additional checking (e.g. enforce SSL). response = func(request, *args, **kwargs) return response