

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 示例 1：带有 OPA 和 Rego 的基本 ABAC
<a name="opa-abac-examples"></a>

本节介绍一种场景，其中使用 OPA 来决定允许哪些用户访问虚构的 Payroll 微服务中的信息。提供 Rego 代码片段是为了演示如何使用 Rego 来呈现访问控制决策。这些例子既不是详尽无遗的，也不是对Rego和OPA能力的全面探索。要更全面地了解 Rego，我们建议您查阅 OPA 网站上的 [Rego 文档](https://www.openpolicyagent.org/docs/latest/#rego)。

![带有 OPA 和 Rego 的基础版 ABAC](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/opa-example-1.png)


## 基本的 OPA 规则示例
<a name="basic-rules"></a>

在上图中，OPA 为工资单微服务强制执行的访问控制规则之一是：

*员工可以读取自己的工资。*

如果 Bob 尝试访问 Payroll 微服务以查看自己的工资，Payroll 微服务可以将 API 调用重定向到 OPA RESTful API 以做出访问决定。工资单服务使用以下 JSON 输入查询 OPA 以获取决策：

```
{
    "user": "bob",
    "method": "GET",
    "path": ["getSalary", "bob"]
}
```

OPA 根据查询选择一个或多个策略。在这种情况下，以下用 Rego 编写的策略将评估 JSON 输入。

```
default allow = false
allow = true {
    input.method == "GET"
    input.path = ["getSalary", user]
    input.user == user
}
```

默认情况下，此策略拒绝访问。然后，它通过将查询中的输入绑定到全局变量`input`来评估该输入。点运算符用于此变量来访问变量的值。如果规则中的表达式也为真，Rego 规则将`allow`返回 true。Rego 规则验证输入`method`中的是否等于 GET。然后，它会验证列表中的第一个元素`path`是否存在，然后`getSalary`再将列表中的第二个元素赋给该变量`user`。最后，它`/getSalary/bob`通过检查发出请求的人是否与`user`变量匹配来检查正在访问的路径。`user` `input.user`该规则`allow`应用 if-then 逻辑来返回布尔值，如输出所示：

```
{
    "allow": true
}
```

## 使用外部数据的部分规则
<a name="partial-rules"></a>

要演示其他 OPA 功能，您可以对正在实施的访问规则添加要求。假设您要在上图的上下文中强制执行此访问控制要求： 

*员工可以阅读任何向他们汇报的人的工资。*

在此示例中，OPA 可以访问外部数据，这些数据可以导入以帮助做出访问决策：

```
"managers": {
        "bob": ["dave", "john"],
        "carol": ["alice"]
}
```

 您可以通过在 OPA 中创建部分规则来生成任意 JSON 响应，该规则返回一组值而不是固定响应。这是部分规则的示例：

```
direct_report[user_ids] {
    user_ids = data.managers[input.user][_]
}
```

 此规则返回一组报告到值的所有用户`input.user`，在本例中为`bob`。规则中的`[_]`构造用于迭代集合的值。这是规则的输出：

```
{
    "direct_report": [
      "dave",
      "john"
    ]
}
```

检索此信息有助于确定用户是否是经理的直接下属。对于某些应用程序，返回动态 JSON 比返回简单的布尔响应更可取。

## 组合起来
<a name="abac-combination"></a>

最后一个访问要求比前两个要求更复杂，因为它结合了两个要求中指定的条件：

*员工可以阅读自己的工资和向他们汇报的任何人的工资。*

要满足此要求，您可以使用此 Rego 政策：

```
default allow = false
 
allow = true {
    input.method == "GET"
    input.path = ["getSalary", user]
    input.user == user
}
 
allow = true {
    input.method == "GET"
    input.path = ["getSalary", user]
    managers := data.managers[input.user][_]
    contains(managers, user)
}
```

如前所述，该政策的第一条规则允许任何试图查看自己的工资信息的用户进行访问。有两个同名的规则`allow`，在 Rego 中用作逻辑**或**运算符。第二条规则检索与之关联的所有直接下属的列表`input.user`（来自上图中的数据），并将此列表分配给变量。`managers`最后，该规则`input.user`通过验证其姓名是否包含在`managers`变量中，来检查试图查看其工资的用户是否是其直接下属。

本节中的示例非常基本，并未提供对 Rego 和 OPA 功能的完整或彻底探索。[有关更多信息，请查看 [OPA 文档，查看 OPA 自述文件](https://www.openpolicyagent.org/docs/latest/)，然后在 [ GitHub Rego P](https://github.com/open-policy-agent/opa) layground 中进行实验。](https://play.openpolicyagent.org/)