“CBAC”的版本间的差异
| (未显示同一用户的2个中间版本) | |||
| 第1行: | 第1行: | ||
| − | + | <meta property="mw:pageId" content="75" /> | |
| − | |||
| − | <meta property="mw:pageId" content="75" /> | ||
<meta property="mw:pageNamespace" content="0" /> | <meta property="mw:pageNamespace" content="0" /> | ||
| − | <meta property="mw:revisionSHA1" content=" | + | <meta property="mw:revisionSHA1" content="256a4cfa7999ae45eb97cc5690cc00c9c38a6705" /> |
| − | <meta property="dc:modified" content="2026-08- | + | <meta property="dc:modified" content="2026-08-30T23:08:30.000Z" /> |
<meta property="mw:html:version" content="2.1.0" /> | <meta property="mw:html:version" content="2.1.0" /> | ||
| − | [https://www.smartlegalcontract.cn/mediawiki/index.php/CBAC] | + | [https://www.smartlegalcontract.cn/mediawiki/index.php/CBAC][/mediawiki/load.php?modules=mediawiki.skinning.content.parsoid%7Cmediawiki.skinning.interface%7Csite.styles%7Cmediawiki.page.gallery.styles%7Cext.cite.style%7Cext.cite.styles%7Cext.pygments%7Cext.pygments&only=styles&skin=vector] |
<meta http-equiv="content-language" content="zh-cn" /> | <meta http-equiv="content-language" content="zh-cn" /> | ||
<meta http-equiv="vary" content="Accept" /> | <meta http-equiv="vary" content="Accept" /> | ||
| + | = 概述 | ||
| + | <meta property="mw:pageId" content="75" /> | ||
| + | <meta property="mw:pageNamespace" content="0" /> | ||
| + | |||
| + | <meta property="mw:revisionSHA1" content="256a4cfa7999ae45eb97cc5690cc00c9c38a6705" /> | ||
| + | <meta property="dc:modified" content="2026-08-30T23:08:30.000Z" /> | ||
| + | <meta property="mw:html:version" content="2.1.0" /> | ||
| + | [https://www.smartlegalcontract.cn/mediawiki/index.php/CBAC] = | ||
| + | |||
| + | [/mediawiki/load.php?modules=mediawiki.skinning.content.parsoid%7Cmediawiki.skinning.interface%7Csite.styles%7Cmediawiki.page.gallery.styles%7Cext.cite.style%7Cext.cite.styles%7Cext.pygments%7Cext.pygments&only=styles&skin=vector]1、主体 | ||
| + | <meta property="mw:pageId" content="75" /> | ||
| + | <meta property="mw:pageNamespace" content="0" /> | ||
| + | |||
| + | <meta property="mw:revisionSHA1" content="256a4cfa7999ae45eb97cc5690cc00c9c38a6705" /> | ||
| + | <meta property="dc:modified" content="2026-08-30T23:08:30.000Z" /> | ||
| + | <meta property="mw:html:version" content="2.1.0" /> | ||
| + | [https://www.smartlegalcontract.cn/mediawiki/index.php/CBAC]注册时签[/mediawiki/load.php?modules=mediawiki.skinning.content.parsoid%7Cmediawiki.skinning.interface%7Csite.styles%7Cmediawiki.page.gallery.styles%7Cext.cite.style%7Cext.cite.styles%7Cext.pygments%7Cext.pygments&only=styles&skin=vector]主体合约,资源托管时签客体合约;两份合约放入同一个 policySet,按业务场景组合 | ||
| − | + | - policySet 是未签署的组合框架,policy 是一份已签署合约 | |
| + | |||
| + | - CBAC 是主文档,主体合约 + 客体合约,两份都签署 | ||
| + | |||
| + | - SPESC 是执行投影。判决投影管 Permit/Deny,执行投影管付费、分账、违约 | ||
| + | |||
| + | - 因为 SPESC 本身只有立约和付款,装不下访问控制和角色派生,CBAC 补这一层 | ||
| + | |||
| + | 2、原始 SPESC 格式不能破坏,只能追加: | ||
| + | |||
| + | - party / asset / term 原样保留 | ||
| + | |||
| + | - term 管法律权利义务 | ||
| + | |||
| + | - access 管访问控制判决 | ||
| + | |||
| + | 3、关联: | ||
| + | |||
| + | - policy 里的 party / asset 是属性字典,给 access 提供 subject.role、resource.type 这类取值 | ||
| + | |||
| + | - policySet 里的 request 是统一输入,告诉引擎 subject 对应谁、resource 对应谁 | ||
| + | |||
| + | - 授权/角色派生 SPESC 没有,所以 term 动作带实参,是显式扩展。 | ||
| + | |||
| + | - term 的授权动作调用先执行,把角色派生结果交给 access 用 | ||
| + | |||
| + | 4、找到的xacml没有托管合约下的语义,于是Platform 义务按需补,简单例子就只留 party/asset/term/access。 | ||
| + | |||
| + | 5、后续使用: | ||
| + | |||
| + | - 授权中心按 sub/obj 找到两份合约 | ||
| + | |||
| + | - 请求只带 Subid / Objid / Act | ||
| + | |||
| + | - 判决引擎只读 access和授权动作调用派生的属性,不读 term 的 must / while / where / breach | ||
| + | |||
| + | - term 的付费、分账、违约留给 SPESC 投影 | ||
| + | |||
| + | - Permit 后生成具体 SPESC,再发 token;资源中心验 token 放行;放行后触发链上具体 SPESC 执行 | ||
| + | |||
| + | - 判决和执行读同一份主文档,但读的部分不同,所以视图一致性用双 AST 检查兜底 | ||
| + | |||
| + | <meta charset="utf-8" /> | ||
| + | <title>CBAC</title> | ||
=例1:基础policy,OASIS 规范正式例子的起点= | =例1:基础policy,OASIS 规范正式例子的起点= | ||
| 第60行: | 第118行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==逻辑结构:== | ==逻辑结构:== | ||
| − | Policy SimplePolicy1 (deny-overrides) ├── Target = 空(适用于所有请求) └── Rule SimpleRule1 (Permit) | + | Policy SimplePolicy1 (deny-overrides) |
| − | + | ||
| − | + | ├── Target = 空(适用于所有请求) | |
| + | |||
| + | └── Rule SimpleRule1 (Permit) | ||
| + | |||
| + | ├── 描述:med.example.com 域内的邮箱主体可以对任意资源执行任意动作 | ||
| + | |||
| + | └── Target: subject-id (rfc822Name) 匹配 "med.example.com" | ||
==属性表:== | ==属性表:== | ||
| − | + | | `subject-id` | access-subject | `rfc822Name` | | |
| − | |||
| − | | `subject-id` | access-subject | `rfc822Name` | ||
==原始请求等效json:== | ==原始请求等效json:== | ||
| 第92行: | 第154行: | ||
==转换版:== | ==转换版:== | ||
policySet "OASIS3_5_MediCorpAccess" { | policySet "OASIS3_5_MediCorpAccess" { | ||
| − | + | ||
| + | // CBAC 追加:请求模型(判决引擎统一输入) | ||
| + | |||
| + | request AuthorizationRequest { | ||
| + | |||
| + | subject: Subject | ||
| + | |||
| + | resource: Resource | ||
| + | |||
| + | action: Action | ||
| + | |||
| + | environment: Environment | ||
| + | |||
| + | } | ||
| + | |||
| + | combine denyOverrides // XACML 上层组合逻辑 | ||
| + | |||
| + | policy "MediCorpInternalAccess" signedBy [Subject, Platform] { | ||
| + | |||
| + | party Subject { // SPESC 原生参与方 ---- | ||
| + | |||
| + | subjectId: rfc822Name | ||
| + | |||
| + | name: String | ||
| + | |||
| + | department: String | ||
| + | |||
| + | employmentStatus: String | ||
| + | |||
| + | } | ||
| + | |||
| + | party Platform { // Platform 的“系统设计义务”,由 SPESC term 声明。 | ||
| + | |||
| + | account: String | ||
| + | |||
| + | authorize(role: String, subjectId: String) // 身份/角色管理 | ||
| + | |||
| + | audit(actionId: String, subjectId: String) // 安全/合规执行 | ||
| + | |||
| + | suspend(subjectId: String) // 治理/处罚 | ||
| + | |||
| + | revoke(subjectId: String) // 生命周期终止 | ||
| + | |||
| + | } | ||
| + | |||
| + | // ---- SPESC 原生:资产 ---- | ||
| + | |||
| + | asset Resource { | ||
| + | |||
| + | info { | ||
| + | |||
| + | resourceId: String | ||
| + | |||
| + | resourceType: String | ||
| + | |||
| + | department: String | ||
| + | |||
| + | } | ||
| + | |||
| + | right { } | ||
| + | |||
| + | } | ||
| + | |||
| + | // ---- SPESC term:法律/义务声明(不参与 Permit/Deny)--- | ||
| + | |||
| + | // 身份与角色管理:平台有义务为域内用户派生 internal-user 角色 | ||
| + | |||
| + | term IdentityRoleManagement: Platform must authorize("internal-user", Subject::subjectId) | ||
| + | |||
| + | when Subject::subjectId endsWith "@med.example.com". | ||
| + | |||
| + | // 安全与合规执行:平台有义务对访问动作审计 | ||
| + | |||
| + | term SecurityComplianceAudit: Platform must audit(action.actionId, Subject::subjectId) | ||
| + | |||
| + | when action.actionId in ["read", "download", "export"]. | ||
| + | |||
| + | // 生命周期治理:员工离岗时平台有义务吊销访问资格 | ||
| + | |||
| + | term LifecycleRevoke: Platform must revoke(Subject::subjectId) | ||
| + | |||
| + | when Subject::employmentStatus = "terminated". | ||
| + | |||
| + | combine permitOverrides // XACML 下层组合逻辑 | ||
| + | |||
| + | access "AnyMedDomainUserAnyAction" { // 原始 XACML 规则:域内用户可对任何资源执行任何动作 | ||
| + | |||
| + | target { | ||
| + | |||
| + | subject.subjectId endsWith "@med.example.com" | ||
| + | |||
| + | } | ||
| + | |||
| + | effect Permit | ||
| + | |||
| + | } | ||
| + | |||
| + | signature { algorithm "ECDSA"; keyId "medi-subject-template-001"; digest "sha256:..." } | ||
| + | |||
| + | signature { algorithm "ECDSA"; keyId "medi-platform-001"; digest "sha256:..." } | ||
| + | |||
| + | } | ||
| + | |||
| + | } | ||
| + | |||
| + | | ||
| + | =例2:rbac组合= | ||
| + | 来源:https://docs.oasis-open.org/xacml/3.0/xacml-3.0-core-spec-os-en.html#_Toc325047096 语法:单条 Policy + 单条 Rule,Policy 级 Target 为空,Rule 级 Target 用 rfc822Name-match 对请求里的 subject-id 做邮箱域匹配;没有 Condition、Obligation、PolicySet。相比 WSO2 的 string-equal/集合比较,这里第一次出现“带类型的函数语义”(RFC822 邮箱域名匹配) | ||
| + | ==原文:== | ||
| + | <syntaxhighlight lang="xml"> | ||
| + | <Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" PolicyId="testOr" RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable" Version="1.0"> | ||
| + | <Description>Test Or</Description> | ||
| + | <Target></Target> | ||
| + | <Rule Effect="Permit" RuleId="primary-group-emps-rule"> //Rule1:read + 组命中 admin_emps/admin → 保护接口 | ||
| + | <Target> | ||
| + | <AnyOf> | ||
| + | <AllOf> | ||
| + | <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> | ||
| + | <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">read</AttributeValue> | ||
| + | <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"/> | ||
| + | </Match> | ||
| + | </AllOf> | ||
| + | </AnyOf> | ||
| + | </Target> | ||
| + | <Condition> | ||
| + | <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of"> | ||
| + | <AttributeDesignator AttributeId="group" DataType="http://www.w3.org/2001/XMLSchema#string" Category="urn:oasis:names:tc:xacml:3.0:group" MustBePresent="true"/> | ||
| + | <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-bag"> | ||
| + | <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin_emps</AttributeValue> | ||
| + | <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin</AttributeValue> | ||
| + | </Apply> | ||
| + | </Apply> | ||
| + | </Condition> | ||
| + | </Rule> | ||
| + | <Rule Effect="Permit" RuleId="primary-user-rule"> //Rule2:公开版本接口,任何用户 | ||
| + | <Condition> | ||
| + | <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of"> | ||
| + | <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"/> | ||
| + | <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-bag"> | ||
| + | <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">http://localhost:8280/services/Customers/getVersion1</AttributeValue> | ||
| + | <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">http://localhost:8280/services/Customers/getVersion2</AttributeValue> | ||
| + | </Apply> | ||
| + | </Apply> | ||
| + | </Condition> | ||
| + | </Rule> | ||
| + | <Rule Effect="Deny" RuleId="deny-rule"></Rule> | ||
| + | </Policy> | ||
| + | </syntaxhighlight> | ||
| + | ==逻辑结构:== | ||
| + | Policy (组合: first-applicable) | ||
| + | |||
| + | ├── Target = 空 | ||
| + | |||
| + | ├── Rule1 (Permit) | ||
| + | |||
| + | │ ├── Target: action-id = read | ||
| + | |||
| + | │ └── Condition: group 属性 (类别 group)与 {admin_emps, admin} 有交集 | ||
| + | |||
| + | ├── Rule2 (Permit) | ||
| + | |||
| + | │ ├── Target: 无 | ||
| + | |||
| + | │ └── Condition: resource-id 与 {http://localhost:8280/services/Customers/getVersion1, http://localhost:8280/services/Customers/getVersion2} 有交集 | ||
| + | |||
| + | └── Rule3 (Deny) 兜底 | ||
| + | ==属性表:== | ||
| + | | `action-id` | `action` | string | | ||
| + | |||
| + | | `group` | `group` | string | | ||
| + | |||
| + | | `resource-id` | `resource` | string | | ||
| + | ==原始请求等效json: == | ||
| + | { | ||
| + | "sub": { | ||
| + | "subjectId": "alice", | ||
| + | "groups": ["admin"] | ||
| + | }, | ||
| + | "obj": { | ||
| + | "resourceId": "http://localhost:8280/services/Customers/getVersion1" | ||
| + | }, | ||
| + | "act": { | ||
| + | "actionId": "read" | ||
| + | } | ||
| + | } | ||
| + | ==转换版说明:== | ||
| + | 把原策略的 3 条 Rule 直接翻成 3 条 access,没有加任何 Platform 义务 | ||
| + | ==转换版:== | ||
| + | policySet "WSO2_Sample6_TestOr" { | ||
request AuthorizationRequest { | request AuthorizationRequest { | ||
subject: Subject | subject: Subject | ||
| 第99行: | 第349行: | ||
environment: Environment | environment: Environment | ||
} | } | ||
| − | + | type Action { | |
| − | + | actionId: string | |
| − | + | } | |
| − | policy " | + | type Environment { |
| − | + | currentTime: dateTime | |
| − | party Subject { | + | } |
| − | subjectId: | + | combine firstApplicable |
| − | + | policy "testOr" { | |
| − | + | party Subject { | |
| − | + | subjectId: string | |
| + | groups: string[] // 原 XACML 的 group category | ||
| + | readResource() // 动作声明 | ||
} | } | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
asset Resource { | asset Resource { | ||
info { | info { | ||
| − | resourceId: | + | resourceId: string |
| − | |||
| − | |||
} | } | ||
right { } | right { } | ||
} | } | ||
| − | + | term PublicVersionRead: Subject can readResource | |
| − | + | when Resource::resourceId in [ | |
| − | + | "http://localhost:8280/services/Customers/getVersion1", | |
| − | + | "http://localhost:8280/services/Customers/getVersion2" | |
| − | term | + | ]. |
| − | when | + | combine firstApplicable |
| − | + | access "PrimaryGroupEmpsRule" { | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | combine | ||
| − | |||
| − | access " | ||
target { | target { | ||
| − | subject. | + | action.actionId = "read" |
| + | } | ||
| + | condition { | ||
| + | some g in subject.groups | ||
| + | such that g in ["admin_emps", "admin"] | ||
| + | } | ||
| + | effect Permit | ||
| + | } | ||
| + | access "PrimaryUserRule" { | ||
| + | condition { | ||
| + | resource.resourceId in [ | ||
| + | "http://localhost:8280/services/Customers/getVersion1", | ||
| + | "http://localhost:8280/services/Customers/getVersion2" | ||
| + | ] | ||
} | } | ||
effect Permit | effect Permit | ||
} | } | ||
| − | + | access "DenyRule" { | |
| − | + | effect Deny | |
| − | + | } | |
} | } | ||
} | } | ||
* | * | ||
2026年8月31日 (一) 01:12的最新版本
<meta property="mw:pageId" content="75" /> <meta property="mw:pageNamespace" content="0" />
<meta property="mw:revisionSHA1" content="256a4cfa7999ae45eb97cc5690cc00c9c38a6705" /> <meta property="dc:modified" content="2026-08-30T23:08:30.000Z" /> <meta property="mw:html:version" content="2.1.0" /> [1][/mediawiki/load.php?modules=mediawiki.skinning.content.parsoid%7Cmediawiki.skinning.interface%7Csite.styles%7Cmediawiki.page.gallery.styles%7Cext.cite.style%7Cext.cite.styles%7Cext.pygments%7Cext.pygments&only=styles&skin=vector] <meta http-equiv="content-language" content="zh-cn" /> <meta http-equiv="vary" content="Accept" /> = 概述 <meta property="mw:pageId" content="75" /> <meta property="mw:pageNamespace" content="0" />
<meta property="mw:revisionSHA1" content="256a4cfa7999ae45eb97cc5690cc00c9c38a6705" /> <meta property="dc:modified" content="2026-08-30T23:08:30.000Z" /> <meta property="mw:html:version" content="2.1.0" /> [2] =
[/mediawiki/load.php?modules=mediawiki.skinning.content.parsoid%7Cmediawiki.skinning.interface%7Csite.styles%7Cmediawiki.page.gallery.styles%7Cext.cite.style%7Cext.cite.styles%7Cext.pygments%7Cext.pygments&only=styles&skin=vector]1、主体 <meta property="mw:pageId" content="75" /> <meta property="mw:pageNamespace" content="0" />
<meta property="mw:revisionSHA1" content="256a4cfa7999ae45eb97cc5690cc00c9c38a6705" /> <meta property="dc:modified" content="2026-08-30T23:08:30.000Z" /> <meta property="mw:html:version" content="2.1.0" /> [3]注册时签[/mediawiki/load.php?modules=mediawiki.skinning.content.parsoid%7Cmediawiki.skinning.interface%7Csite.styles%7Cmediawiki.page.gallery.styles%7Cext.cite.style%7Cext.cite.styles%7Cext.pygments%7Cext.pygments&only=styles&skin=vector]主体合约,资源托管时签客体合约;两份合约放入同一个 policySet,按业务场景组合
- policySet 是未签署的组合框架,policy 是一份已签署合约
- CBAC 是主文档,主体合约 + 客体合约,两份都签署
- SPESC 是执行投影。判决投影管 Permit/Deny,执行投影管付费、分账、违约
- 因为 SPESC 本身只有立约和付款,装不下访问控制和角色派生,CBAC 补这一层
2、原始 SPESC 格式不能破坏,只能追加:
- party / asset / term 原样保留
- term 管法律权利义务
- access 管访问控制判决
3、关联:
- policy 里的 party / asset 是属性字典,给 access 提供 subject.role、resource.type 这类取值
- policySet 里的 request 是统一输入,告诉引擎 subject 对应谁、resource 对应谁
- 授权/角色派生 SPESC 没有,所以 term 动作带实参,是显式扩展。
- term 的授权动作调用先执行,把角色派生结果交给 access 用
4、找到的xacml没有托管合约下的语义,于是Platform 义务按需补,简单例子就只留 party/asset/term/access。
5、后续使用:
- 授权中心按 sub/obj 找到两份合约
- 请求只带 Subid / Objid / Act
- 判决引擎只读 access和授权动作调用派生的属性,不读 term 的 must / while / where / breach
- term 的付费、分账、违约留给 SPESC 投影
- Permit 后生成具体 SPESC,再发 token;资源中心验 token 放行;放行后触发链上具体 SPESC 执行
- 判决和执行读同一份主文档,但读的部分不同,所以视图一致性用双 AST 检查兜底
<meta charset="utf-8" /> <title>CBAC</title>
例1:基础policy,OASIS 规范正式例子的起点
来源:https://docs.oasis-open.org/xacml/3.0/xacml-3.0-core-spec-os-en.html#_Toc325047096
语法:单条 Policy + 单条 Rule,Policy 级 Target 为空,Rule 级 Target 用 rfc822Name-match 对请求里的 subject-id 做邮箱域匹配;没有 Condition、Obligation、PolicySet。相比 WSO2 的 string-equal/集合比较,这里第一次出现“带类型的函数语义”(RFC822 邮箱域名匹配)
原文:
<?xml version="1.0" encoding="UTF-8"?>
<Policy
xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17
http://docs.oasis-open.org/xacml/3.0/xacml-core-v3-schema-wd-17.xsd"
PolicyId="urn:oasis:names:tc:xacml:3.0:example:SimplePolicy1"
Version="1.0"
RuleCombiningAlgId="identifier:rule-combining-algorithm:deny-overrides">
<Description>
Medi Corp access control policy
</Description>
<Target/>
<Rule
RuleId="urn:oasis:names:tc:xacml:3.0:example:SimpleRule1"
Effect="Permit">
<Description>
Any subject with an e-mail name in the med.example.com domain
can perform any action on any resource.
</Description>
<Target>
<AnyOf>
<AllOf>
<Match
MatchId="urn:oasis:names:tc:xacml:1.0:function:rfc822Name-match">
<AttributeValue
DataType="http://www.w3.org/2001/XMLSchema#string"
>med.example.com</AttributeValue>
<AttributeDesignator
MustBePresent="false"
Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id"
DataType="urn:oasis:names:tc:xacml:1.0:data-type:rfc822Name"/>
</Match>
</AllOf>
</AnyOf>
</Target>
</Rule>
</Policy>逻辑结构:
Policy SimplePolicy1 (deny-overrides)
├── Target = 空(适用于所有请求)
└── Rule SimpleRule1 (Permit)
├── 描述:med.example.com 域内的邮箱主体可以对任意资源执行任意动作
└── Target: subject-id (rfc822Name) 匹配 "med.example.com"
属性表:
| `subject-id` | access-subject | `rfc822Name` |
原始请求等效json:
{
"sub": {
"subjectId": "bart.simpson@med.example.com"
},
"obj": {
"resourceId": "file://example/med/record/patient/BartSimpson"
},
"act": {
"actionId": "read"
}
}
转换版说明:
- 原例是单一企业内部访问策略,不是本课题“平台托管双合约”场景。为自圆其说,将其置于“Medi Corp 内部医疗资源平台”语境:
-- Platform 承担身份/角色管理、核心业务授权、安全合规、生命周期治理义务;
- 原 XACML 只有主体域约束,因此本文件只含一份 policy,不强行拆两份合约。
- 映射: rfc822Name-match("med.example.com", subject-id) -> subject.subjectId endsWith "@med.example.com"
- 原始请求之外需要获取的其它信息:
转换版:
policySet "OASIS3_5_MediCorpAccess" {
// CBAC 追加:请求模型(判决引擎统一输入)
request AuthorizationRequest {
subject: Subject
resource: Resource
action: Action
environment: Environment
}
combine denyOverrides // XACML 上层组合逻辑
policy "MediCorpInternalAccess" signedBy [Subject, Platform] {
party Subject { // SPESC 原生参与方 ----
subjectId: rfc822Name
name: String
department: String
employmentStatus: String
}
party Platform { // Platform 的“系统设计义务”,由 SPESC term 声明。
account: String
authorize(role: String, subjectId: String) // 身份/角色管理
audit(actionId: String, subjectId: String) // 安全/合规执行
suspend(subjectId: String) // 治理/处罚
revoke(subjectId: String) // 生命周期终止
}
// ---- SPESC 原生:资产 ----
asset Resource {
info {
resourceId: String
resourceType: String
department: String
}
right { }
}
// ---- SPESC term:法律/义务声明(不参与 Permit/Deny)---
// 身份与角色管理:平台有义务为域内用户派生 internal-user 角色
term IdentityRoleManagement: Platform must authorize("internal-user", Subject::subjectId)
when Subject::subjectId endsWith "@med.example.com".
// 安全与合规执行:平台有义务对访问动作审计
term SecurityComplianceAudit: Platform must audit(action.actionId, Subject::subjectId)
when action.actionId in ["read", "download", "export"].
// 生命周期治理:员工离岗时平台有义务吊销访问资格
term LifecycleRevoke: Platform must revoke(Subject::subjectId)
when Subject::employmentStatus = "terminated".
combine permitOverrides // XACML 下层组合逻辑
access "AnyMedDomainUserAnyAction" { // 原始 XACML 规则:域内用户可对任何资源执行任何动作
target {
subject.subjectId endsWith "@med.example.com"
}
effect Permit
}
signature { algorithm "ECDSA"; keyId "medi-subject-template-001"; digest "sha256:..." }
signature { algorithm "ECDSA"; keyId "medi-platform-001"; digest "sha256:..." }
}
}
例2:rbac组合
来源:https://docs.oasis-open.org/xacml/3.0/xacml-3.0-core-spec-os-en.html#_Toc325047096 语法:单条 Policy + 单条 Rule,Policy 级 Target 为空,Rule 级 Target 用 rfc822Name-match 对请求里的 subject-id 做邮箱域匹配;没有 Condition、Obligation、PolicySet。相比 WSO2 的 string-equal/集合比较,这里第一次出现“带类型的函数语义”(RFC822 邮箱域名匹配)
原文:
<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" PolicyId="testOr" RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable" Version="1.0">
<Description>Test Or</Description>
<Target></Target>
<Rule Effect="Permit" RuleId="primary-group-emps-rule"> //Rule1:read + 组命中 admin_emps/admin → 保护接口
<Target>
<AnyOf>
<AllOf>
<Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">read</AttributeValue>
<AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"/>
</Match>
</AllOf>
</AnyOf>
</Target>
<Condition>
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of">
<AttributeDesignator AttributeId="group" DataType="http://www.w3.org/2001/XMLSchema#string" Category="urn:oasis:names:tc:xacml:3.0:group" MustBePresent="true"/>
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-bag">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin_emps</AttributeValue>
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin</AttributeValue>
</Apply>
</Apply>
</Condition>
</Rule>
<Rule Effect="Permit" RuleId="primary-user-rule"> //Rule2:公开版本接口,任何用户
<Condition>
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of">
<AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"/>
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-bag">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">http://localhost:8280/services/Customers/getVersion1</AttributeValue>
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">http://localhost:8280/services/Customers/getVersion2</AttributeValue>
</Apply>
</Apply>
</Condition>
</Rule>
<Rule Effect="Deny" RuleId="deny-rule"></Rule>
</Policy>逻辑结构:
Policy (组合: first-applicable)
├── Target = 空
├── Rule1 (Permit)
│ ├── Target: action-id = read
│ └── Condition: group 属性 (类别 group)与 {admin_emps, admin} 有交集
├── Rule2 (Permit)
│ ├── Target: 无
│ └── Condition: resource-id 与 {http://localhost:8280/services/Customers/getVersion1, http://localhost:8280/services/Customers/getVersion2} 有交集
└── Rule3 (Deny) 兜底
属性表:
| `action-id` | `action` | string |
| `group` | `group` | string |
| `resource-id` | `resource` | string |
原始请求等效json:
{
"sub": {
"subjectId": "alice",
"groups": ["admin"]
},
"obj": {
"resourceId": "http://localhost:8280/services/Customers/getVersion1"
},
"act": {
"actionId": "read"
}
}
转换版说明:
把原策略的 3 条 Rule 直接翻成 3 条 access,没有加任何 Platform 义务
转换版:
policySet "WSO2_Sample6_TestOr" {
request AuthorizationRequest {
subject: Subject
resource: Resource
action: Action
environment: Environment
}
type Action {
actionId: string
}
type Environment {
currentTime: dateTime
}
combine firstApplicable
policy "testOr" {
party Subject {
subjectId: string
groups: string[] // 原 XACML 的 group category
readResource() // 动作声明
}
asset Resource {
info {
resourceId: string
}
right { }
}
term PublicVersionRead: Subject can readResource
when Resource::resourceId in [
"http://localhost:8280/services/Customers/getVersion1",
"http://localhost:8280/services/Customers/getVersion2"
].
combine firstApplicable
access "PrimaryGroupEmpsRule" {
target {
action.actionId = "read"
}
condition {
some g in subject.groups
such that g in ["admin_emps", "admin"]
}
effect Permit
}
access "PrimaryUserRule" {
condition {
resource.resourceId in [
"http://localhost:8280/services/Customers/getVersion1",
"http://localhost:8280/services/Customers/getVersion2"
]
}
effect Permit
}
access "DenyRule" {
effect Deny
}
}
}