Exemple #1
0
def ValidateAccessAndSubjects(requested_access, subjects):
    """Does basic requested access validation.

  Args:
    requested_access: String consisting or 'r', 'w' and 'q' characters.
    subjects: A list of subjects that are about to be accessed with a
              given requested_access. Used for logging purposes only.

  Returns:
    True if requested_access is valid.

  Raises:
    access_control.UnauthorizedAccess: if requested_access is not valid.
    ValueError: if subjects list is empty.
  """

    if not requested_access:
        raise access_control.UnauthorizedAccess(
            "Must specify requested access type for %s" % subjects)

    for s in requested_access:
        if s not in "rwq":
            raise ValueError("Invalid access requested for %s: %s" %
                             (subjects, requested_access))

    if "q" in requested_access and "r" not in requested_access:
        raise access_control.UnauthorizedAccess(
            "Invalid access request: query permissions require read permissions "
            "for %s" % subjects,
            requested_access=requested_access)

    return True
Exemple #2
0
    def _CheckApprovalsForTokenWithReason(self, token, target):
        # Build the approval URN.
        approval_urn = aff4.ROOT_URN.Add("ACL").Add(target.Path()).Add(
            token.username).Add(utils.EncodeReasonString(token.reason))

        try:
            cached_token = self.acl_cache.Get(approval_urn)
            stats.STATS.IncrementCounter("approval_searches",
                                         fields=["with_reason", "cache"])
            token.is_emergency = cached_token.is_emergency

            return True
        except KeyError:
            stats.STATS.IncrementCounter("approval_searches",
                                         fields=["with_reason", "data_store"])
            try:
                approval_request = aff4.FACTORY.Open(
                    approval_urn,
                    aff4_type=security.Approval.__name__,
                    mode="r",
                    token=token,
                    age=aff4.ALL_TIMES)

                if approval_request.CheckAccess(token):
                    # Cache this approval for fast path checking.
                    self.acl_cache.Put(approval_urn, token)
                    return True

                raise access_control.UnauthorizedAccess(
                    "Approval %s was rejected." % approval_urn, subject=target)

            except IOError:
                # No Approval found, reject this request.
                raise access_control.UnauthorizedAccess(
                    "No approval found for %s." % target, subject=target)
Exemple #3
0
    def CheckAccess(self, handler, username):
        """Check access against ACL file, if defined.

    Args:
      handler: handler class object
      username: username string

    Raises:
      access_control.UnauthorizedAccess: If the handler is listed in the ACL
      file, but the user isn't authorized. Or if enabled_by_default=False and no
      ACL applies.
    """
        handler_name = handler.__class__.__name__
        if handler_name in self.ACLedHandlers():
            if not self._CheckPermission(username, handler_name):
                stats.STATS.IncrementCounter("grr_api_auth_fail",
                                             fields=[handler_name, username])
                raise access_control.UnauthorizedAccess(
                    "User %s not authorized for handler %s." %
                    (username, handler_name))
        elif not handler.enabled_by_default:
            raise access_control.UnauthorizedAccess(
                "%s has enabled_by_default=False and no explicit ACL set. Add ACL"
                " to ACL list (see API.HandlerACLFile config option) to use "
                "this API" % handler)

        logging.debug("Authorizing %s for API %s", username, handler_name)
        stats.STATS.IncrementCounter("grr_api_auth_success",
                                     fields=[handler_name, username])
Exemple #4
0
  def CheckAccess(self, token):
    """Enforce a dual approver policy for access."""
    namespace, _ = self.urn.Split(2)

    if namespace != "ACL":
      raise access_control.UnauthorizedAccess(
          "Approval object has invalid urn %s." % self.urn,
          subject=self.urn,
          requested_access=token.requested_access)

    user, subject_urn = self.InferUserAndSubjectFromUrn()
    if user != token.username:
      raise access_control.UnauthorizedAccess(
          "Approval object is not for user %s." % token.username,
          subject=self.urn,
          requested_access=token.requested_access)

    now = rdfvalue.RDFDatetime.Now()

    # Is this an emergency access?
    break_glass = self.Get(self.Schema.BREAK_GLASS)
    if break_glass and now < break_glass:
      # This tags the token as an emergency token.
      token.is_emergency = True
      return True

    # Check that there are enough approvers.
    approvers = self.GetNonExpiredApprovers()
    if len(approvers) < config_lib.CONFIG["ACL.approvers_required"]:
      msg = ("Requires %s approvers for access." %
             config_lib.CONFIG["ACL.approvers_required"])
      raise access_control.UnauthorizedAccess(
          msg, subject=subject_urn, requested_access=token.requested_access)

    # Check User labels
    if self.checked_approvers_label:
      approvers_with_label = []

      # We need to check labels with high privilege since normal users can
      # inspect other user's labels.
      for approver in approvers:
        try:
          user = aff4.FACTORY.Open(
              "aff4:/users/%s" % approver,
              aff4_type=aff4_users.GRRUser,
              token=token.SetUID())
          if self.checked_approvers_label in user.GetLabelsNames():
            approvers_with_label.append(approver)
        except IOError:
          pass

      if len(approvers_with_label) < self.min_approvers_with_label:
        raise access_control.UnauthorizedAccess(
            "At least %d approver(s) should have '%s' label." %
            (self.min_approvers_with_label, self.checked_approvers_label),
            subject=subject_urn,
            requested_access=token.requested_access)

    return True
Exemple #5
0
  def RenderAjax(self, request, response):
    """Run the flow for granting access."""
    approval_urn = rdfvalue.RDFURN(request.REQ.get("acl", "/"))
    _, namespace, _ = approval_urn.Split(3)

    if namespace == "hunts":
      try:
        _, _, hunt_id, user, reason = approval_urn.Split()
        self.subject = rdfvalue.RDFURN(namespace).Add(hunt_id)
        self.user = user
        self.reason = utils.DecodeReasonString(reason)
      except (ValueError, TypeError):
        raise access_control.UnauthorizedAccess(
            "Approval object is not well formed.")

      flow.GRRFlow.StartFlow(flow_name="GrantHuntApprovalFlow",
                             subject_urn=self.subject,
                             reason=self.reason,
                             delegate=self.user,
                             token=request.token)
    elif namespace == "cron":
      try:
        _, _, cron_job_name, user, reason = approval_urn.Split()
        self.subject = rdfvalue.RDFURN(namespace).Add(cron_job_name)
        self.user = user
        self.reason = utils.DecodeReasonString(reason)
      except (ValueError, TypeError):
        raise access_control.UnauthorizedAccess(
            "Approval object is not well formed.")

      flow.GRRFlow.StartFlow(flow_name="GrantCronJobApprovalFlow",
                             subject_urn=self.subject,
                             reason=self.reason,
                             delegate=self.user,
                             token=request.token)
    elif aff4.AFF4Object.VFSGRRClient.CLIENT_ID_RE.match(namespace):
      try:
        _, client_id, user, reason = approval_urn.Split()
        self.subject = client_id
        self.user = user
        self.reason = utils.DecodeReasonString(reason)
      except (ValueError, TypeError):
        raise access_control.UnauthorizedAccess(
            "Approval object is not well formed.")

      flow.GRRFlow.StartFlow(client_id=client_id,
                             flow_name="GrantClientApprovalFlow",
                             reason=self.reason,
                             delegate=self.user,
                             subject_urn=rdf_client.ClientURN(self.subject),
                             token=request.token)
    else:
      raise access_control.UnauthorizedAccess(
          "Approval object is not well formed.")

    return renderers.TemplateRenderer.Layout(self,
                                             request,
                                             response,
                                             apply_template=self.ajax_template)
Exemple #6
0
    def CheckACL(self, token, target):
        # The supervisor may bypass all ACL checks.
        if token.supervisor:
            logging.debug(u"ACL access granted to %s on %s. Supervisor: %s",
                          utils.SmartUnicode(token.username), target,
                          token.supervisor)
            return True

        # Target may be None for flows not specifying a client.
        # Only aff4.GRRUser.SYSTEM_USERS can run these flows.
        if not target:
            if token.username not in aff4.GRRUser.SYSTEM_USERS:
                raise access_control.UnauthorizedAccess(
                    "ACL access denied for flow without client_urn for %s" %
                    token.username)

            return True

        if not token.reason:
            raise access_control.UnauthorizedAccess(
                "Must specify a reason for access.", subject=target)

        # Build the approval URN.
        approval_urn = aff4.ROOT_URN.Add("ACL").Add(target.Path()).Add(
            token.username).Add(utils.EncodeReasonString(token.reason))

        try:
            token.is_emergency = self.acl_cache.Get(approval_urn)
            logging.debug(u"ACL access granted to %s on %s. Supervisor: %s",
                          utils.SmartUnicode(token.username), target,
                          token.supervisor)
            return True
        except KeyError:
            try:
                # Retrieve the approval object with superuser privileges so we can check
                # it.
                approval_request = aff4.FACTORY.Open(approval_urn,
                                                     aff4_type="Approval",
                                                     mode="r",
                                                     token=self.super_token,
                                                     age=aff4.ALL_TIMES)

                if approval_request.CheckAccess(token):
                    # Cache this approval for fast path checking.
                    self.acl_cache.Put(approval_urn, token.is_emergency)
                    logging.debug(
                        u"ACL access granted to %s on %s. Supervisor: %s",
                        utils.SmartUnicode(token.username), target,
                        token.supervisor)
                    return True

                raise access_control.UnauthorizedAccess(
                    "Approval %s was rejected." % approval_urn, subject=target)

            except IOError:
                # No Approval found, reject this request.
                raise access_control.UnauthorizedAccess(
                    "No approval found for %s." % target, subject=target)
  def _CheckArtifactCollectorFlowArgs(self, flow_args):
    if not self.params.artifact_collector_flow.enabled:
      raise access_control.UnauthorizedAccess(
          "ArtifactCollectorFlow flow is not allowed by the configuration")

    for name in flow_args.artifact_list:
      if name not in self.params.artifact_collector_flow.artifacts_whitelist:
        raise access_control.UnauthorizedAccess(
            "Artifact %s is not whitelisted." % name)
Exemple #8
0
    def ValidateRequestedAccess(self, requested_access, subjects):
        if not requested_access:
            raise access_control.UnauthorizedAccess(
                "Must specify requested access type for %s" % subjects)

        if "q" in requested_access and "r" not in requested_access:
            raise access_control.UnauthorizedAccess(
                "Invalid access request: query permissions require read permissions "
                "for %s" % subjects,
                requested_access=requested_access)
Exemple #9
0
    def UserHasClientApproval(self, subject, token):
        """Checks if read access for this client is allowed using the given token.

    Args:
      subject: Subject below the client level which triggered the check.
      token: The token to check with.

    Returns:
      True if the access is allowed.

    Raises:
      UnauthorizedAccess: if the access is rejected.
    """
        client_id, _ = rdfvalue.RDFURN(subject).Split(2)
        client_urn = rdfvalue.ClientURN(client_id)

        logging.debug("Checking client approval for %s, %s", client_urn, token)

        if not token.reason:
            raise access_control.UnauthorizedAccess(
                "Must specify a reason for access.", subject=client_urn)

        # Build the approval URN.
        approval_urn = aff4.ROOT_URN.Add("ACL").Add(client_urn.Path()).Add(
            token.username).Add(utils.EncodeReasonString(token.reason))

        try:
            token.is_emergency = self.acl_cache.Get(approval_urn)
            return True
        except KeyError:
            try:
                # Retrieve the approval object with superuser privileges so we can check
                # it.
                approval_request = aff4.FACTORY.Open(approval_urn,
                                                     aff4_type="Approval",
                                                     mode="r",
                                                     token=self.super_token,
                                                     age=aff4.ALL_TIMES)

                if approval_request.CheckAccess(token):
                    # Cache this approval for fast path checking.
                    self.acl_cache.Put(approval_urn, token.is_emergency)
                    return True

                raise access_control.UnauthorizedAccess(
                    "Approval %s was rejected." % approval_urn,
                    subject=client_urn)

            except IOError:
                # No Approval found, reject this request.
                raise access_control.UnauthorizedAccess(
                    "No approval found for client %s." % client_urn,
                    subject=client_urn)
Exemple #10
0
  def CheckMethodIsAccessChecked(self,
                                 method,
                                 access_type,
                                 args=None,
                                 token=None):
    token = token or self.token

    # Check that legacy access control manager is called and that the method
    # is then delegated.
    method(args, token=token)
    self.assertTrue(getattr(self.legacy_manager_mock, access_type).called)
    getattr(self.delegate_mock, method.__name__).assert_called_with(
        args, token=token)

    self.delegate_mock.reset_mock()
    self.legacy_manager_mock.reset_mock()

    try:
      # Check that when exception is raised by legacy manager, the delegate
      # method is not called.
      getattr(self.legacy_manager_mock,
              access_type).side_effect = access_control.UnauthorizedAccess("")

      with self.assertRaises(access_control.UnauthorizedAccess):
        method(args, token=token)

      self.assertTrue(getattr(self.legacy_manager_mock, access_type).called)
      self.assertFalse(getattr(self.delegate_mock, method.__name__).called)

    finally:
      getattr(self.legacy_manager_mock, access_type).side_effect = None
      self.delegate_mock.reset_mock()
      self.legacy_manager_mock.reset_mock()
Exemple #11
0
def CheckFlowCanBeStartedAsGlobal(flow_name):
    """Checks if flow can be started without a client id.

  Two kinds of flows can be started on clients by unprivileged users:
  1) ACL_ENFORCED=False flows, because they're expected to do their own ACL
     checking and are often used by AdminUI to execute code with elevated
     privileges.
  2) Flows inherited from GRRGlobalFlow, with a category. Having a category
     means that the flow will be accessible from the UI.

  Args:
    flow_name: Name of the flow to check access for.
  Returns:
    True if flow is externally accessible.
  Raises:
    access_control.UnauthorizedAccess: if flow is not externally accessible.
  """
    flow_cls = flow.GRRFlow.GetPlugin(flow_name)

    if (not flow_cls.ACL_ENFORCED
            or aff4.issubclass(flow_cls, flow.GRRGlobalFlow)
            and flow_cls.category):
        return True
    else:
        raise access_control.UnauthorizedAccess(
            "Flow %s can't be started globally by non-suid users" % flow_name)
Exemple #12
0
  def Layout(self, request, response):
    """Launch the RequestApproval flow on the backend."""
    self.acl = request.REQ.get("acl")

    source = request.REQ.get("source")

    if self.acl is None and source != "hash":
      # NOTE: we have to pass id explicitly because super().Layout() wasn't
      # called yet, and therefore self.id is None.
      return self.CallJavascript(
          response,
          "GrantAccess.RefreshFromHash",
          renderer=self.__class__.__name__,
          id=request.REQ.get("id", hash(self)))

    # TODO(user): This makes assumptions about the approval URL.
    approval_urn = rdfvalue.RDFURN(self.acl or "/")
    components = approval_urn.Split()
    username = components[-2]
    namespace = components[1]

    _, namespace, _ = approval_urn.Split(3)
    if namespace == "hunts":
      self.details_renderer = "HuntApprovalDetailsRenderer"
      self.user = components[3]
      self.detail_header = "Hunt Information"
    elif namespace == "cron":
      self.details_renderer = "CronJobApprovalDetailsRenderer"
      self.user = components[3]
      self.detail_header = "Cronjob Information"
    elif aff4_grr.VFSGRRClient.CLIENT_ID_RE.match(namespace):
      self.details_renderer = "ClientApprovalDetailsRenderer"
      self.user = components[2]
      self.detail_header = "Client Information"
    else:
      raise access_control.UnauthorizedAccess(
          "Approval object is not well formed.")

    approval_request = aff4.FACTORY.Open(
        approval_urn, mode="r", age=aff4.ALL_TIMES, token=request.token)
    self.user = username
    self.reason = approval_request.Get(approval_request.Schema.REASON)

    user_token = access_control.ACLToken(username=self.user, reason=self.reason)
    self.already_approved_text = ""
    self.btn_cls = "btn btn-success"
    try:
      if approval_request.CheckAccess(user_token):
        self.already_approved_text = "This approval has already been granted!"
        self.btn_cls = "btn btn-warning"
    except access_control.UnauthorizedAccess:
      pass

    response = renderers.TemplateRenderer.Layout(self, request, response)
    return self.CallJavascript(
        response,
        "GrantAccess.Layout",
        renderer=self.__class__.__name__,
        acl=self.acl,
        details_renderer=self.details_renderer)
Exemple #13
0
    def CreateFlow(self, args, token=None):
        # CreateFlow is used for starting both client flows and global flows.
        # By not allowing client_id to be empty we explicitly forbid starting
        # global flows through robot router.
        # TODO(user): introduce separate API call for starting global flows.
        if not args.client_id:
            raise ValueError("client_id must be provided")

        override_flow_args = None
        throttler = None
        if args.flow.name == self.file_finder_flow_name:
            self._CheckFileFinderArgs(args.flow.args)
            override_flow_args = self._FixFileFinderArgs(args.flow.args)
            throttler = self._GetFileFinderThrottler()
        elif args.flow.name == self.artifact_collector_flow_name:
            self._CheckArtifactCollectorFlowArgs(args.flow.args)
            throttler = self._GetArtifactCollectorFlowThrottler()
        else:
            raise access_control.UnauthorizedAccess(
                "Creating arbitrary flows (%s) is not allowed." %
                args.flow.name)

        try:
            throttler.EnforceLimits(args.client_id.ToClientURN(),
                                    token.username,
                                    args.flow.name,
                                    args.flow.args,
                                    token=token)
        except throttle.ErrorFlowDuplicate as e:
            # If a similar flow did run recently, just return it.
            return ApiRobotReturnDuplicateFlowHandler(flow_urn=e.flow_urn)

        return ApiRobotCreateFlowHandler(robot_id=self.params.robot_id,
                                         override_flow_args=override_flow_args)
Exemple #14
0
    def ValidateToken(self, token, target):
        """Validate Basic Token Issues."""
        # All accesses need a token.
        if not token:
            raise access_control.UnauthorizedAccess(
                "Must give an authorization token for %s" % target,
                subject=target)

        # Token must not be expired here.
        token.CheckExpiry()

        # Token must have identity
        if not token.username:
            raise access_control.UnauthorizedAccess(
                "Must specify a username for access to %s." % target,
                subject=target)
Exemple #15
0
def CheckFlowCanBeStartedOnClient(flow_name):
    """Checks if flow can be started on a particular client.

  Two kinds of flows can be started on clients by unprivileged users:
  1) ACL_ENFORCED=False flows, because they're expected to do their own ACL
     checking and are often used by AdminUI to execute code with elevated
     privileges.
  2) Flows with a category. Having a category means that the flow will be
     accessible from the UI.

  Args:
    flow_name: Name of the flow to check access for.
  Returns:
    True if flow is externally accessible.
  Raises:
    access_control.UnauthorizedAccess: if flow is not externally accessible.
  """
    flow_cls = flow.GRRFlow.GetPlugin(flow_name)

    if not flow_cls.ACL_ENFORCED or flow_cls.category:
        return True
    else:
        raise access_control.UnauthorizedAccess(
            "Flow %s can't be started on a client by non-suid users." %
            flow_name)
Exemple #16
0
    def CreateFlow(self, args, token=None):
        # CreateFlow is used for starting both client flows and global flows.
        # By not allowing client_id to be empty we explicitly forbid starting
        # global flows through robot router.
        # TODO(user): introduce separate API call for starting global flows.
        if not args.client_id:
            raise ValueError("client_id must be provided")

        throttler = None
        if args.flow.name == self.file_finder_flow_name:
            self._CheckFileFinderArgs(args.flow.args)
            throttler = self._GetFileFinderThrottler()
        elif args.flow.name == self.artifact_collector_flow_name:
            self._CheckArtifactCollectorFlowArgs(args.flow.args)
            throttler = self._GetArtifactCollectorFlowThrottler()
        else:
            raise access_control.UnauthorizedAccess(
                "Creating arbitrary flows (%s) is not allowed." %
                args.flow.name)

        throttler.EnforceLimits(args.client_id,
                                token.username,
                                args.flow.name,
                                args.flow.args,
                                token=token)

        return ApiRobotCreateFlowHandler(robot_id=self.params.robot_id)
Exemple #17
0
    def GetFlow(self, args, token=None):
        if not self.params.get_flow.enabled:
            raise access_control.UnauthorizedAccess(
                "GetFlow is not allowed by the configuration.")

        self._CheckFlowRobotId(args.client_id, args.flow_id, token=token)

        return api_flow.ApiGetFlowHandler()
Exemple #18
0
    def ListFlowResults(self, args, token=None):
        if not self.params.list_flow_results.enabled:
            raise access_control.UnauthorizedAccess(
                "ListFlowResults is not allowed by the configuration.")

        self._CheckFlowRobotId(args.client_id, args.flow_id, token=token)

        return api_flow.ApiListFlowResultsHandler()
Exemple #19
0
    def CheckCronJobAccess(self, token, cron_job_urn):
        """Checks access to a given cron job.

    Args:
      token: User credentials token.
      cron_job_urn: URN of cron job to check.

    Returns:
      True if access is allowed, raises otherwise.

    Raises:
      access_control.UnauthorizedAccess if access is rejected.
    """
        logging.debug("Checking approval for cron job %s, %s", cron_job_urn,
                      token)

        if not token.username:
            raise access_control.UnauthorizedAccess(
                "Must specify a username for access.", subject=cron_job_urn)

        if not token.reason:
            raise access_control.UnauthorizedAccess(
                "Must specify a reason for access.", subject=cron_job_urn)

        # Build the approval URN.
        approval_urn = aff4.ROOT_URN.Add("ACL").Add(cron_job_urn.Path()).Add(
            token.username).Add(utils.EncodeReasonString(token.reason))

        try:
            approval_request = aff4.FACTORY.Open(approval_urn,
                                                 aff4_type="Approval",
                                                 mode="r",
                                                 token=token,
                                                 age=aff4.ALL_TIMES)
        except IOError:
            # No Approval found, reject this request.
            raise access_control.UnauthorizedAccess(
                "No approval found for cron job %s." % cron_job_urn,
                subject=cron_job_urn)

        if approval_request.CheckAccess(token):
            return True
        else:
            raise access_control.UnauthorizedAccess(
                "Approval %s was rejected." % approval_urn,
                subject=cron_job_urn)
  def CheckUserLabels(self, username, authorized_labels, token=None):
    """Verify that the username has all the authorized_labels set."""
    authorized_labels = set(authorized_labels)

    try:
      user = aff4.FACTORY.Open("aff4:/users/%s" % username, aff4_type="GRRUser",
                               token=token)

      # Only return if all the authorized_labels are found in the user's
      # label list, otherwise raise UnauthorizedAccess.
      if (authorized_labels.intersection(user.GetLabels()) ==
          authorized_labels):
        return
      raise access_control.UnauthorizedAccess(
          "User %s is missing labels (required: %s)." % (username,
                                                         authorized_labels))
    except IOError:
      raise access_control.UnauthorizedAccess("User %s not found." % username)
Exemple #21
0
    def Start(self):
        """Create the Approval object and notify the Approval Granter."""
        approval_urn = self.BuildApprovalUrn()
        subject_title = self.BuildSubjectTitle()
        access_urn = self.BuildAccessUrl()

        # This object must already exist.
        try:
            approval_request = aff4.FACTORY.Open(approval_urn,
                                                 mode="rw",
                                                 aff4_type=self.approval_type,
                                                 token=self.token)
        except IOError:
            raise access_control.UnauthorizedAccess(
                "Approval object does not exist.", requested_access="rw")

        # We are now an approver for this request.
        approval_request.AddAttribute(
            approval_request.Schema.APPROVER(self.token.username))
        approval_request.Close(sync=True)

        # Notify to the user.
        fd = aff4.FACTORY.Create(aff4.ROOT_URN.Add("users").Add(
            self.args.delegate),
                                 "GRRUser",
                                 mode="rw",
                                 token=self.token)

        fd.Notify(
            "ViewObject", self.args.subject_urn,
            "%s has granted you access to %s." %
            (self.token.username, subject_title), self.session_id)
        fd.Close()

        template = """
<html><body><h1>Access to %(subject_title)s granted.</h1>

The user %(username)s has granted access to %(subject_title)s for the
purpose of "%(reason)s".

Please click <a href='%(admin_ui)s#%(subject_urn)s'>here</a> to access it.

<p>Thanks,</p>
<p>The GRR team.
</body></html>"""

        email_alerts.SendEmail(self.args.delegate,
                               self.token.username,
                               "Access to %s granted." % subject_title,
                               template %
                               dict(subject_title=subject_title,
                                    username=self.token.username,
                                    reason=utils.SmartStr(self.args.reason),
                                    admin_ui=config_lib.CONFIG["AdminUI.url"],
                                    subject_urn=access_urn),
                               is_html=True)
Exemple #22
0
  def InferUserAndSubjectFromUrn(self):
    """Infers user name and subject urn from self.urn."""
    _, cron_str, cron_job_name, user, _ = self.urn.Split(5)

    if cron_str != "cron":
      raise access_control.UnauthorizedAccess(
          "Approval object has invalid urn %s." % self.urn,
          requested_access=self.token.requested_access)

    return (user, aff4.ROOT_URN.Add("cron").Add(cron_job_name))
Exemple #23
0
    def Layout(self, request, response):
        """Launch the RequestApproval flow on the backend."""
        self.acl = request.REQ.get("acl")

        source = request.REQ.get("source")

        if self.acl is None and source != "hash":
            # NOTE: we have to pass id explicitly because super().Layout() wasn't
            # called yet, and therefore self.id is None.
            return self.CallJavascript(response,
                                       "GrantAccess.RefreshFromHash",
                                       renderer=self.__class__.__name__,
                                       id=request.REQ.get("id", hash(self)))

        # There is a bug in Firefox that strips trailing "="s from get parameters
        # which is a problem with the base64 padding. To pass the selenium tests,
        # we have to restore the original string.
        while len(self.acl.split("/")[-1]) % 4 != 0:
            self.acl += "="

        # TODO(user): This makes assumptions about the approval URL.
        approval_urn = rdfvalue.RDFURN(self.acl or "/")
        components = approval_urn.Split()
        username = components[-2]
        namespace = components[1]

        _, namespace, _ = approval_urn.Split(3)
        if namespace == "hunts":
            self.details_renderer = "HuntApprovalDetailsRenderer"
            self.user = components[3]
            self.detail_header = "Hunt Information"
        elif namespace == "cron":
            self.details_renderer = "CronJobApprovalDetailsRenderer"
            self.user = components[3]
            self.detail_header = "Cronjob Information"
        elif aff4.AFF4Object.VFSGRRClient.CLIENT_ID_RE.match(namespace):
            self.details_renderer = "ClientApprovalDetailsRenderer"
            self.user = components[2]
            self.detail_header = "Client Information"
        else:
            raise access_control.UnauthorizedAccess(
                "Approval object is not well formed.")

        approval_request = aff4.FACTORY.Open(approval_urn,
                                             mode="r",
                                             token=request.token)

        self.user = username
        self.reason = approval_request.Get(approval_request.Schema.REASON)
        response = renderers.TemplateRenderer.Layout(self, request, response)
        return self.CallJavascript(response,
                                   "GrantAccess.Layout",
                                   renderer=self.__class__.__name__,
                                   acl=self.acl,
                                   details_renderer=self.details_renderer)
  def CheckFlowAccess(self, token, flow_name, client_id=None):
    """Checks access to the given flow.

    Args:
      token: User credentials token.
      flow_name: Name of the flow to check.
      client_id: Client id of the client where the flow is going to be
                 started. Defaults to None.

    Returns:
      True if access is allowed, raises otherwise.

    Raises:
      access_control.UnauthorizedAccess if access is rejected.
    """
    client_urn = None
    if client_id:
      client_urn = rdfvalue.ClientURN(client_id)

    if not token:
      raise access_control.UnauthorizedAccess(
          "Must give an authorization token for flow %s" % flow_name)

    # Token must not be expired here.
    token.CheckExpiry()

    # The supervisor may bypass all ACL checks.
    if token.supervisor:
      return True

    flow_cls = flow.GRRFlow.GetPlugin(flow_name)

    # Flows which are not enforced can run all the time.
    if not flow_cls.ACL_ENFORCED:
      return True

    if not client_urn:
      raise access_control.UnauthorizedAccess(
          "Mortals are only allowed to run flows on the client.")

    # This should raise in case of failure.
    return self.UserHasClientApproval(client_urn, token)
Exemple #25
0
    def CheckApproversForLabel(self, token, client_urn, requester, approvers,
                               label):
        """Checks if requester and approvers have approval privileges for labels.

    Checks against list of approvers for each label defined in approvers.yaml to
    determine if the list of approvers is sufficient.

    Args:
      token: user token
      client_urn: ClientURN object of the client
      requester: username string of person requesting approval.
      approvers: list of username strings that have approved this client.
      label: label strings to check approval privs for.
    Returns:
      True if access is allowed, raises otherwise.
    """
        auth = self.reader.GetAuthorizationForSubject(label)
        if not auth:
            # This label isn't listed in approvers.yaml
            return True

        if auth.requester_must_be_authorized:
            if not self.CheckPermissions(requester, label):
                raise access_control.UnauthorizedAccess(
                    "User %s not in %s or groups:%s for %s" %
                    (requester, auth.users, auth.groups, label),
                    subject=client_urn,
                    requested_access=token.requested_access)

        approved_count = 0
        for approver in approvers:
            if self.CheckPermissions(approver,
                                     label) and approver != requester:
                approved_count += 1

        if approved_count < auth.num_approvers_required:
            raise access_control.UnauthorizedAccess(
                "Found %s approvers for %s, needed %s" %
                (approved_count, label, auth.num_approvers_required),
                subject=client_urn,
                requested_access=token.requested_access)
        return True
Exemple #26
0
    def _CheckFileFinderArgs(self, flow_args, token=None):
        ffparams = self.params.file_finder_flow

        if not ffparams.enabled:
            raise access_control.UnauthorizedAccess(
                "FileFinder flow is not allowed by the configuration.")

        if not ffparams.globs_allowed:
            for path in flow_args.paths:
                str_path = utils.SmartStr(path)
                if "*" in str_path:
                    raise access_control.UnauthorizedAccess(
                        "Globs are not allowed by the configuration.")

        if not ffparams.interpolations_allowed:
            for path in flow_args.paths:
                str_path = utils.SmartStr(path)
                if "%%" in str_path:
                    raise access_control.UnauthorizedAccess(
                        "Interpolations are not allowed by the configuration.")
 def IsHomeDir(self, subject, token):
   """Checks user access permissions for paths under aff4:/users."""
   h = CheckAccessHelper("IsHomeDir")
   h.Allow("aff4:/users/%s" % token.username)
   h.Allow("aff4:/users/%s/*" % token.username)
   try:
     return h.CheckAccess(subject, token)
   except access_control.UnauthorizedAccess:
     raise access_control.UnauthorizedAccess("User can only access his "
                                             "home directory.",
                                             subject=subject)
Exemple #28
0
    def _CheckFlowRobotId(self, client_id, flow_id, token=None):
        flow_urn = flow_id.ResolveClientFlowURN(client_id, token=token)
        fd = aff4.FACTORY.Open(flow_urn, aff4_type=flow.GRRFlow, token=token)

        needed_label_name = LABEL_NAME_PREFIX + self.params.robot_id
        if needed_label_name not in fd.GetLabelsNames():
            raise access_control.UnauthorizedAccess(
                "Flow %s (client %s) does not have a proper robot id label set."
                % (flow_id, client_id))

        return fd
Exemple #29
0
def ValidateToken(token, targets):
  """Does basic token validation.

  Args:
    token: User's credentials as access_control.ACLToken.
    targets: List of targets that were meant to be accessed by the token.
             This is used for logging purposes only.
  Returns:
    True if token is valid.

  Raises:
    access_control.UnauthorizedAccess: if token is not valid.
    ValueError: if targets list is empty.
  """

  def GetSubjectForError():
    if len(targets) == 1:
      return list(targets)[0]
    else:
      return None

  # All accesses need a token.
  if not token:
    raise access_control.UnauthorizedAccess(
        "Must give an authorization token for %s" % targets,
        subject=GetSubjectForError())

  # Token must not be expired here.
  token.CheckExpiry()

  # Token must have identity
  if not token.username:
    raise access_control.UnauthorizedAccess(
        "Must specify a username for access to %s." % targets,
        subject=GetSubjectForError())

  return True
Exemple #30
0
    def CheckClientLabels(self, client_id, token=None):
        has_label = False
        with aff4.FACTORY.Open(client_id.ToClientURN(),
                               aff4_type=aff4_grr.VFSGRRClient,
                               token=token) as fd:
            for label in fd.GetLabels():
                if (label.name in self.labels_whitelist
                        and label.owner in self.labels_owners_whitelist):
                    has_label = True
                    break

        if not has_label:
            raise access_control.UnauthorizedAccess(
                "Client %s doesn't have necessary labels." %
                utils.SmartStr(client_id))