OPA
Open Policy Agent (OPA) 集成
⚠️ 预览功能
OPA 集成目前是一项预览功能,未来版本可能会发生不兼容的变更。请谨慎在生产环境中使用。
本页介绍如何将 Apache Polaris 与 Open Policy Agent (OPA) 集成,以实现外部授权。
概述
Open Policy Agent (OPA) 是一个通用策略引擎,可在整个技术栈中实现统一的、基于上下文的策略执行。OPA 提供了高层级的声明式语言(Rego)用于编写策略,并提供 API,从而将策略决策从你的软件中卸载出来。
将 OPA 与 Polaris 结合使用的主要优势:
- 灵活的策略语言:使用强大的声明式语言 Rego 编写授权逻辑
- 集中式策略管理:在单一位置管理所有策略
- 策略测试:为授权策略编写单元测试
- 丰富的生态系统:可与策略包、决策日志以及管理工具集成
- 基于属性的访问控制:根据用户属性、资源特性和环境上下文做出决策
前置条件
在配置 OPA 集成之前:
- OPA 服务器:部署并配置一个 Polaris 可以访问的 OPA 服务器
- 策略定义:编写授权策略并部署到 OPA
- 网络访问:确保 Polaris 能够连接到 OPA 服务器
快速开始
1. 部署 OPA
使用你的策略部署 OPA 服务器。例如,使用 Docker:
docker run -d \
--name opa \
-p 8181:8181 \
-v $(pwd)/policies:/policies \
openpolicyagent/opa:latest \
run --server --addr :8181 /policies2. 创建策略
创建一个策略文件(例如 policies/polaris.rego):
package polaris.authz
import future.keywords.if
# Default deny
default allow := false
# Allow admins to do everything
allow if {
"ADMIN" in input.actor.roles
}
# Allow read operations on tables in analytics catalogs
allow if {
input.action == "LOAD_TABLE_WITH_READ_DELEGATION"
some target in input.resource.targets
some parent in target.parents
parent.type == "CATALOG"
startswith(parent.name, "analytics_")
}3. 配置 Polaris
在 Polaris 配置中添加以下内容:
# Enable OPA authorization
polaris.authorization.type=opa
# OPA server endpoint
polaris.authorization.opa.policy-uri=http://<opa-host>:8181/v1/data/polaris/authz4. 重启 Polaris
重启 Polaris 服务以应用配置。
配置参考
基本配置
| 属性 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|
polaris.authorization.type | 是 | internal | 设置为 opa 以启用 OPA 授权 |
polaris.authorization.opa.policy-uri | 是 | - | OPA 策略决策端点的完整 URI(必须为 http 或 https) |
HTTP 配置
| 属性 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|
polaris.authorization.opa.http.timeout | 否 | PT2S | HTTP 请求超时时间(ISO-8601 时长格式,例如 PT2S、PT10S) |
polaris.authorization.opa.http.verify-ssl | 否 | true | 是否验证 SSL 证书 |
polaris.authorization.opa.http.trust-store-path | 否 | - | 包含 CA 证书的信任库路径 |
polaris.authorization.opa.http.trust-store-password | 否 | - | 信任库的密码 |
认证配置
OPA 集成支持两种认证模式:
无认证(默认)
如果 OPA 服务器不要求认证,则无需进行认证配置:
polaris.authorization.opa.auth.type=noneBearer Token 认证
静态 Bearer Token:
使用静态 Bearer Token:
polaris.authorization.opa.auth.type=bearer
polaris.authorization.opa.auth.bearer.static-token.value=your-secret-token| 属性 | 是否必需 | 默认值 | 说明 |
|---|---|---|---|
polaris.authorization.opa.auth.type | 否 | none | 设置为 bearer 以启用 Bearer 令牌认证 |
polaris.authorization.opa.auth.bearer.static-token.value | 是* | - | Bearer 令牌的值(*使用静态令牌时必填) |
基于文件的 Bearer 令牌与自动刷新:
使用来自文件的 Bearer 令牌并支持自动刷新(非常适合 JWT 令牌):
polaris.authorization.opa.auth.type=bearer
polaris.authorization.opa.auth.bearer.file-based.path=/var/secrets/token.txt
polaris.authorization.opa.auth.bearer.file-based.refresh-interval=PT5M
polaris.authorization.opa.auth.bearer.file-based.jwt-expiration-refresh=true
polaris.authorization.opa.auth.bearer.file-based.jwt-expiration-buffer=PT1M| 属性 | 必填 | 默认值 | 描述 |
|---|---|---|---|
polaris.authorization.opa.auth.type | 否 | none | 设置为 bearer 以启用 Bearer 令牌认证 |
polaris.authorization.opa.auth.bearer.file-based.path | 是* | - | 包含 Bearer 令牌的文件路径(*使用基于文件的令牌时必填) |
polaris.authorization.opa.auth.bearer.file-based.refresh-interval | 否 | - | 刷新令牌的频率(ISO-8601 持续时间,例如 PT5M 表示 5 分钟)。若未设置且 JWT 刷新被禁用,令牌将不会被刷新 |
polaris.authorization.opa.auth.bearer.file-based.jwt-expiration-refresh | 否 | true | 自动检测 JWT 令牌并根据过期时间进行刷新 |
polaris.authorization.opa.auth.bearer.file-based.jwt-expiration-buffer | 否 | PT1M | 在 JWT 过期前触发刷新的缓冲时间(ISO-8601 持续时间) |
JWT 自动刷新:当 jwt-expiration-refresh 启用时(默认启用),如果令牌文件中包含带有 exp 声明的有效 JWT,Polaris 将根据 jwt-expiration-buffer 设置在令牌过期前不久自动刷新令牌。
策略开发
输入文档结构
Polaris 向 OPA 发送以下输入结构:
{
"actor": {
"principal": "user@example.com",
"roles": ["role1", "role2"]
},
"action": "LOAD_TABLE_WITH_READ_DELEGATION",
"resource": {
"targets": [
{
"type": "TABLE",
"name": "my_table",
"parents": [
{
"type": "CATALOG",
"name": "my_catalog"
},
{
"type": "NAMESPACE",
"name": "schema1"
}
]
}
],
"secondaries": []
},
"context": {
"request_id": "uuid"
}
}行为主体对象(Actor Object)
| 字段 | 类型 | 描述 |
|---|---|---|
principal | string | 主体标识符(例如用户名、服务账号) |
roles | array | 分配给该主体的角色名称数组 |
操作字段(Action Field)
action 字段包含正在尝试执行的操作,其值为 PolarisAuthorizableOperation 枚举中的字符串。
可用操作的完整列表请参见源代码中的 PolarisAuthorizableOperation 枚举。
常见示例包括:
- 表操作:
LOAD_TABLE_WITH_READ_DELEGATION、LOAD_TABLE_WITH_WRITE_DELEGATION、CREATE_TABLE_DIRECT、UPDATE_TABLE、DROP_TABLE_WITHOUT_PURGE - 目录操作:
CREATE_CATALOG、UPDATE_CATALOG、DELETE_CATALOG - 命名空间操作:
CREATE_NAMESPACE、UPDATE_NAMESPACE_PROPERTIES、DROP_NAMESPACE
⚠️ 重要的策略注意事项
显式处理所有数据操作:编写 OPA 策略时,请显式处理所有启用目录、命名空间和表操作的 PolarisAuthorizableOperation 值。未被你的策略规则覆盖的操作将回退到你的默认决策。我们建议:
- 设置
default allow := false,以便默认拒绝 - 仅显式允许用户实际需要的操作
仅限内部使用的操作:某些操作(如 CREATE_POLICY)用于管理 Polaris 的内部权限系统。在 OPA 策略中应始终拒绝这些操作,因为权限管理应通过 Polaris 的原生授权系统处理,而不是通过外部策略。
资源对象(Resource Object)
| 字段 | 类型 | 描述 |
|---|---|---|
targets | array | 目标资源对象数组(正在访问的主要资源) |
secondaries | array | 次要资源对象数组(相关资源,如有) |
targets 或 secondaries 中的每个资源对象都包含:
| 字段 | 类型 | 描述 |
|---|---|---|
type | string | 资源类型(CATALOG、NAMESPACE、TABLE、VIEW、PRINCIPAL、CATALOG_ROLE 等) |
name | string | 资源名称 |
parents | array | 层级结构中父级资源对象的数组(例如,某张表的父级为目录和命名空间) |
每个父级对象包含:
| 字段 | 类型 | 描述 |
|---|---|---|
type | string | 父资源类型 |
name | string | 父资源名称 |
上下文对象
| 字段 | 类型 | 描述 |
|---|---|---|
request_id | string | 用于将请求与日志关联的 UUID |
策略示例
package polaris.authz
import future.keywords.if
import future.keywords.in
default allow := false
# Admin role can perform all catalog, namespace, and table operations
allow if {
"ADMIN" in input.actor.roles
input.action in [
# Catalog operations
"CREATE_CATALOG",
"UPDATE_CATALOG",
"DELETE_CATALOG",
"LIST_CATALOGS",
# Namespace operations
"CREATE_NAMESPACE",
"UPDATE_NAMESPACE_PROPERTIES",
"DROP_NAMESPACE",
"LIST_NAMESPACES",
# Table operations
"CREATE_TABLE_DIRECT",
"LOAD_TABLE_WITH_READ_DELEGATION",
"LOAD_TABLE_WITH_WRITE_DELEGATION",
"UPDATE_TABLE",
"DROP_TABLE_WITHOUT_PURGE",
# Add other data operations as needed
]
}
# Data engineers can create/read/update tables and namespaces
allow if {
"DATA_ENGINEER" in input.actor.roles
input.action in [
# Table operations
"CREATE_TABLE_DIRECT",
"LOAD_TABLE_WITH_READ_DELEGATION",
"LOAD_TABLE_WITH_WRITE_DELEGATION",
"UPDATE_TABLE",
# Namespace operations
"CREATE_NAMESPACE",
"UPDATE_NAMESPACE_PROPERTIES",
"LIST_NAMESPACES"
]
}
# Analysts can only read tables
allow if {
"ANALYST" in input.actor.roles
input.action == "LOAD_TABLE_WITH_READ_DELEGATION"
some target in input.resource.targets
target.type == "TABLE"
}ℹ️ 最佳实践
仅为数据操作设置显式允许列表:上面的示例采用显式的允许列表方式,只允许对目录(catalog)、命名空间(namespace)和表(table)进行操作。策略和授权操作(如 CREATE_POLICY)会被 default allow := false 自动拒绝,因为它们不在任何允许规则之中。这确保了权限管理始终保留在 Polaris 原生授权系统之内,并且在未来的 Polaris 版本中新增的操作在你显式允许之前,默认都会被拒绝。
测试策略
OPA 支持使用 opa test 进行策略测试。创建一个测试文件(例如 polaris_test.rego):
package polaris.authz
import future.keywords.if
test_admin_can_create_catalog if {
allow with input as {
"actor": {"principal": "admin", "roles": ["ADMIN"]},
"action": "CREATE_CATALOG",
"resource": {
"targets": [{
"type": "CATALOG",
"name": "new_catalog",
"parents": []
}],
"secondaries": []
},
"context": {"request_id": "test"}
}
}
test_data_engineer_can_create_table if {
allow with input as {
"actor": {"principal": "engineer", "roles": ["DATA_ENGINEER"]},
"action": "CREATE_TABLE_DIRECT",
"resource": {
"targets": [{
"type": "TABLE",
"name": "new_table",
"parents": [
{"type": "CATALOG", "name": "prod"},
{"type": "NAMESPACE", "name": "schema1"}
]
}],
"secondaries": []
},
"context": {"request_id": "test"}
}
}
test_data_engineer_cannot_delete_catalog if {
not allow with input as {
"actor": {"principal": "engineer", "roles": ["DATA_ENGINEER"]},
"action": "DELETE_CATALOG",
"resource": {
"targets": [{
"type": "CATALOG",
"name": "prod",
"parents": []
}],
"secondaries": []
},
"context": {"request_id": "test"}
}
}
test_analyst_can_read_table if {
allow with input as {
"actor": {"principal": "analyst", "roles": ["ANALYST"]},
"action": "LOAD_TABLE_WITH_READ_DELEGATION",
"resource": {
"targets": [{
"type": "TABLE",
"name": "data_table",
"parents": [
{"type": "CATALOG", "name": "prod"},
{"type": "NAMESPACE", "name": "schema1"}
]
}],
"secondaries": []
},
"context": {"request_id": "test"}
}
}
test_analyst_cannot_update_table if {
not allow with input as {
"actor": {"principal": "analyst", "roles": ["ANALYST"]},
"action": "UPDATE_TABLE",
"resource": {
"targets": [{
"type": "TABLE",
"name": "data_table",
"parents": [
{"type": "CATALOG", "name": "prod"},
{"type": "NAMESPACE", "name": "schema1"}
]
}],
"secondaries": []
},
"context": {"request_id": "test"}
}
}运行测试:
opa test policies/附加资源
评论
登录后参与评论
KnowForge