(ctx context.Context, object Object)
| 551 | } |
| 552 | |
| 553 | func (pa *PartialAuthorizer) Authorize(ctx context.Context, object Object) error { |
| 554 | if pa.alwaysTrue { |
| 555 | return nil |
| 556 | } |
| 557 | |
| 558 | // If we have no queries, then no queries can return 'true'. |
| 559 | // So the result is always 'false'. |
| 560 | if len(pa.preparedQueries) == 0 { |
| 561 | return ForbiddenWithInternal(xerrors.Errorf("policy disallows request"), |
| 562 | pa.subjectInput, pa.subjectAction, pa.subjectResourceType, nil) |
| 563 | } |
| 564 | |
| 565 | parsed, err := ast.InterfaceToValue(map[string]interface{}{ |
| 566 | "object": object, |
| 567 | }) |
| 568 | if err != nil { |
| 569 | return xerrors.Errorf("parse object: %w", err) |
| 570 | } |
| 571 | |
| 572 | // How to interpret the results of the partial queries. |
| 573 | // We have a list of queries that are along the lines of: |
| 574 | // `input.object.org_owner = ""; "me" = input.object.owner` |
| 575 | // `input.object.org_owner in {"feda2e52-8bf1-42ce-ad75-6c5595cb297a"} ` |
| 576 | // All these queries are joined by an 'OR'. So we need to run through each |
| 577 | // query, and evaluate it. |
| 578 | // |
| 579 | // In each query, we have a list of the expressions, which should be |
| 580 | // all boolean expressions. In the above 1st example, there are 2. |
| 581 | // These expressions within a single query are `AND` together by rego. |
| 582 | EachQueryLoop: |
| 583 | for _, q := range pa.preparedQueries { |
| 584 | // We need to eval each query with the newly known fields. |
| 585 | results, err := q.Eval(ctx, rego.EvalParsedInput(parsed)) |
| 586 | if err != nil { |
| 587 | err = correctCancelError(err) |
| 588 | return xerrors.Errorf("eval error: %w", err) |
| 589 | } |
| 590 | |
| 591 | // If there are no results, then the query is false. This is because rego |
| 592 | // treats false queries as "undefined". So if any expression is false, the |
| 593 | // result is an empty list. |
| 594 | if len(results) == 0 { |
| 595 | continue EachQueryLoop |
| 596 | } |
| 597 | |
| 598 | // If there is more than 1 result, that means there is more than 1 rule. |
| 599 | // This should not happen, because our query should always be an expression. |
| 600 | // If this every occurs, it is likely the original query was not an expression. |
| 601 | if len(results) > 1 { |
| 602 | continue EachQueryLoop |
| 603 | } |
| 604 | |
| 605 | // Our queries should be simple, and should not yield any bindings. |
| 606 | // A binding is something like 'x := 1'. This binding as an expression is |
| 607 | // 'true', but in our case is unhelpful. We are not analyzing this ast to |
| 608 | // map bindings. So just error out. Similar to above, our queries should |
| 609 | // always be boolean expressions. |
| 610 | if len(results[0].Bindings) > 0 { |
nothing calls this directly
no test coverage detected