外部策略决策点(PDP)

OPA

师成师成· 更新于 2026-09-29· 阅读 23 分钟· 0 次阅读

登录后可跨设备保存划线和私人笔记登录

Open Policy Agent (OPA) 集成

⚠️ 预览功能

OPA 集成目前是一项预览功能,未来版本可能会发生不兼容的变更。请谨慎在生产环境中使用。

本页介绍如何将 Apache Polaris 与 Open Policy Agent (OPA) 集成,以实现外部授权。

概述

Open Policy Agent (OPA) 是一个通用策略引擎,可在整个技术栈中实现统一的、基于上下文的策略执行。OPA 提供了高层级的声明式语言(Rego)用于编写策略,并提供 API,从而将策略决策从你的软件中卸载出来。

将 OPA 与 Polaris 结合使用的主要优势:

  • 灵活的策略语言:使用强大的声明式语言 Rego 编写授权逻辑
  • 集中式策略管理:在单一位置管理所有策略
  • 策略测试:为授权策略编写单元测试
  • 丰富的生态系统:可与策略包、决策日志以及管理工具集成
  • 基于属性的访问控制:根据用户属性、资源特性和环境上下文做出决策

前置条件

在配置 OPA 集成之前:

  1. OPA 服务器:部署并配置一个 Polaris 可以访问的 OPA 服务器
  2. 策略定义:编写授权策略并部署到 OPA
  3. 网络访问:确保 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 /policies

2. 创建策略

创建一个策略文件(例如 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/authz

4. 重启 Polaris

重启 Polaris 服务以应用配置。

配置参考

基本配置

属性是否必填默认值说明
polaris.authorization.type是internal设置为 opa 以启用 OPA 授权
polaris.authorization.opa.policy-uri是-OPA 策略决策端点的完整 URI(必须为 http 或 https)

HTTP 配置

属性是否必填默认值说明
polaris.authorization.opa.http.timeout否PT2SHTTP 请求超时时间(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=none

Bearer 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)

字段类型描述
principalstring主体标识符(例如用户名、服务账号)
rolesarray分配给该主体的角色名称数组

操作字段(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)

字段类型描述
targetsarray目标资源对象数组(正在访问的主要资源)
secondariesarray次要资源对象数组(相关资源,如有)

targets 或 secondaries 中的每个资源对象都包含:

字段类型描述
typestring资源类型(CATALOG、NAMESPACE、TABLE、VIEW、PRINCIPAL、CATALOG_ROLE 等)
namestring资源名称
parentsarray层级结构中父级资源对象的数组(例如,某张表的父级为目录和命名空间)

每个父级对象包含:

字段类型描述
typestring父资源类型
namestring父资源名称

上下文对象

字段类型描述
request_idstring用于将请求与日志关联的 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/

附加资源

评论

登录后参与评论

正在加载评论…