(&self)
| 39 | |
| 40 | impl Evaluate<RequestEvaluationResult> for RequestEvaluator { |
| 41 | fn evaluate(&self) -> Result<RequestEvaluationResult, EvaluateError> { |
| 42 | let matching_policies = self |
| 43 | .request |
| 44 | .operation |
| 45 | .to_resources() |
| 46 | .iter() |
| 47 | .flat_map(|resource| REQUEST_POLICY_REPOSITORY.find_by_resource(resource.to_owned())) |
| 48 | .collect::<Vec<_>>(); |
| 49 | |
| 50 | if matching_policies.is_empty() { |
| 51 | // Since requests handle security critical operations, we want to reject them by default if |
| 52 | // they don't match any policy. Users need to explicitly add the necessary policies to evaluate them. |
| 53 | return Ok(RequestEvaluationResult { |
| 54 | request_id: self.request.id, |
| 55 | status: EvaluationStatus::Rejected, |
| 56 | policy_results: vec![], |
| 57 | }); |
| 58 | } |
| 59 | |
| 60 | let request = Arc::new(self.request.to_owned()); |
| 61 | let mut evaluation_statuses = Vec::new(); |
| 62 | |
| 63 | // Evaluate all matching policies to get the full evaluation result. |
| 64 | for policy in matching_policies { |
| 65 | // Evaluate the request policy rule. |
| 66 | let evaluation_status = self |
| 67 | .policy_rule_evaluator |
| 68 | .evaluate((request.to_owned(), Arc::new(policy.rule))) |
| 69 | .context("failed to evaluate policy rule")?; |
| 70 | |
| 71 | evaluation_statuses.push(evaluation_status); |
| 72 | } |
| 73 | |
| 74 | Ok(RequestEvaluationResult { |
| 75 | request_id: self.request.id, |
| 76 | status: { |
| 77 | if evaluation_statuses |
| 78 | .iter() |
| 79 | .any(|result| result.status == EvaluationStatus::Approved) |
| 80 | { |
| 81 | // If any policy of the request is approved, then the request is approved. |
| 82 | EvaluationStatus::Approved |
| 83 | } else if evaluation_statuses |
| 84 | .iter() |
| 85 | .all(|result| result.status == EvaluationStatus::Rejected) |
| 86 | { |
| 87 | // Only if all policies are rejected then the request is rejected, |
| 88 | // this applies an implicit `OR` between policies. |
| 89 | EvaluationStatus::Rejected |
| 90 | } else { |
| 91 | // Since there are matching policies, but none of them approved or rejected the request, we keep it in the |
| 92 | // pending status until one of the policies evaluates it as approved or rejected. |
| 93 | EvaluationStatus::Pending |
| 94 | } |
| 95 | }, |
| 96 | policy_results: evaluation_statuses, |
| 97 | }) |
| 98 | } |
no test coverage detected