定制 amtgard/ork-iam 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

amtgard/ork-iam

Composer 安装命令:

composer require amtgard/ork-iam

包简介

Amtgard ORK IAM

README 文档

README

IAM implementation for ORNs — the policy engine for parsing ORNs, evaluating claims against requirements, and authorizing policies.

Design

https://docs.google.com/document/d/1iv8trAWMf21VFtsKGLCrheVzUeiQVlZYRGB2rfmtUq0/edit?tab=t.0#heading=h.zfr9cypk79t7

Installation

Requirements:

  • PHP ^8.3
  • ext-json

Policy engine only (bring your own ORN definitions):

composer require amtgard/ork-iam

With standard Amtgard ORN definitions (Attendance, ORK):

composer require amtgard/ork-iam amtgard/ork-iam-orn-definitions

ork-iam provides the IAM engine. It does not ship ORN definition classes itself. Use the companion package amtgard/ork-iam-orn-definitions for the standard set, or register your own (see below).

For local development:

composer install

Version lines

Line Branch Composer constraint Latest tag
1.x (maintenance) 1.x "amtgard/ork-iam": "^1.4" v1.4.0
2.x (current) main "amtgard/ork-iam": "^2.1" v2.1.0

Pin ^1.4 for IDP and existing integrators on the 1.x API. Use ^2.1 for the current ontology API (ServiceCatalog, ornSegmentSchema(), …).

Branching

  • 1.x fixes and minors — branch from 1.x, name feature/1.x/<name>, open PRs against 1.x. Tag releases v1.4.0, v1.5.0, … on 1.x.
  • 2.x features — branch from main, name feature/<name>, open PRs against main. Tag releases v2.1.0, v2.2.0, … on main.

Do not use 1.x/feature/... — it conflicts with the 1.x branch ref.

Introduction

ORK IAM is a policy document system that allows for testing claims against requirements. claims may be bundled into policies. If any claim in a policy is accepted by the requirement on a given object, then the policy is accepted by the requirement; otherwise, it is rejected.

A claim and a policy are not self-enforcing, in the sense that any validly constructed claim can be compared to a requirement; it is up to the system making the comparison to validate that the given claim originated from a trusted source.

A typical method of doing this would be a cryptographic signature of the policy from the trusted source, or a cryptographic signature of an envelope containing the policy, such as embedding the policy in a JWT.

ORN definitions

ClaimFactory and RequirementFactory resolve ORN strings to concrete classes via OrnClassMap. Services must be registered before use — otherwise factories throw InvalidArgumentException.

Standard definitions (optional)

Install amtgard/ork-iam-orn-definitions. That package registers Attendance and ORK claim/requirement classes with OrnClassMap automatically on Composer autoload.

Currently defined there:

Service Claim class Requirement class
Attendance Amtgard\IAM\Definitions\ORN\AttendanceClaim Amtgard\IAM\Definitions\ORN\AttendanceRequirement
ORK Amtgard\IAM\Definitions\ORN\OrkClaim Amtgard\IAM\Definitions\ORN\OrkRequirement

Custom definitions

Define your own ORN classes by extending the framework types:

  • Amtgard\IAM\ORNFormat — proviso layout and valid resources for a service
  • Amtgard\IAM\Allowance\Claim — claim ORN for a service
  • Amtgard\IAM\Requirement\Requirement — requirement ORN for a service

Register them with OrnClassMap before calling the factories:

use Amtgard\IAM\ORN\OrnClassMap;
use Amtgard\IAM\OrkServices;
use MyApp\IAM\AttendanceClaim;
use MyApp\IAM\AttendanceRequirement;

OrnClassMap::registerClaim(OrkServices::Attendance, AttendanceClaim::class);
OrnClassMap::registerRequirement(OrkServices::Attendance, AttendanceRequirement::class);

A typical approach is a bootstrap file loaded via Composer autoload files, the same pattern used by ork-iam-orn-definitions.

ORN ontology

ORK IAM uses a consistent vocabulary for ORN structure. See docs/ORN-ONTOLOGY.md for the full glossary and the planned 2.0.0 rename.

Term 1.x API Meaning
Prefix ServiceIdentifier, getPrefix() Leading segment — who owns the ORN
Schema ornSegmentSchema() Ordered segment labels for a claim/requirement type
Label Orn\OrnSegmentLabel Name of one middle segment in the schema
Offset segmentOffset(), OrnSegmentLabel::offsetIn() Zero-based index of a label in the schema
Value getSegmentValue() Parsed ID in one segment (int, *, or empty)
Binding Proviso (Grant / Condition) Label + value on a parsed claim or requirement
Catalog OrkServices Built-in registry of known prefix and label names

Legacy names (serviceFormat(), getProviso(), ProvisoSlot, …) remain available and are deprecated for removal in 2.0.0.

Custom service identifiers

An ORN has two distinct naming layers at the prefix and schema level:

  1. Prefix — the leading segment (Attendance in Attendance:1:2:…, or any custom name like YourService in YourService:1:Widget/Read). This identifies which integrator or product owns the ORN.
  2. Schema labels — the ordered middle segments returned by ornSegmentSchema() (Configuration, Game, Kingdom, …). Each label names one ORN value segment, not the value itself.

Built-in prefixes (Attendance, ORK, …) normalize to OrkServices cases. Integrators may also register custom prefixes that are not enum members, as long as they match /^[A-Z][A-Za-z0-9]*$/. Each prefix maps to its own claim/requirement classes and serviceFormat() layout.

use Amtgard\IAM\ClaimFactory;
use Amtgard\IAM\ORN\OrnClassMap;
use MyApp\IAM\YourServiceClaim;
use MyApp\IAM\YourServiceRequirement;

OrnClassMap::registerClaim('YourService', YourServiceClaim::class);
OrnClassMap::registerRequirement('YourService', YourServiceRequirement::class);

$claim = ClaimFactory::createOrn('YourService:1:Widget/Read');

Built-in OrkServices names cannot be registered via a custom string key — use the enum overload (OrnClassMap::registerClaim(OrkServices::Attendance, …)). OrnClassMap::validateCustomServiceName() checks that a proposed custom name does not collide with a built-in identifier.

Use getServiceIdentifier() on claims and requirements for the prefix string. getService() remains available when the prefix maps to a built-in OrkServices case.

Custom segment labels

ornSegmentSchema() (or legacy serviceFormat()) may return OrkServices cases, arbitrary strings, or OrnSegmentLabel instances. Unlike prefixes, custom label names are not restricted — integrators can use any non-empty string (tenant-id, org unit, and so on). Strings that exactly match a built-in catalog entry normalize to that OrkServices case.

protected function serviceFormat(): array
{
    return [OrkServices::Configuration, 'tenant-id', 'org unit'];
}

// equivalent preferred form:
protected function ornSegmentSchema(): array
{
    return [OrkServices::Configuration, 'tenant-id', 'org unit'];
}

For an ORN YourService:1:42:7:Widget/Read, the values 1, 42, and 7 map to Configuration, tenant-id, and org unit by offset. Use getSegment('tenant-id') or getSegment(OrnSegmentLabel::from('tenant-id')) to read a binding. getSegmentLabel() and getSegmentValue() are the preferred accessors on binding objects.

Alternative: Application prefix

OrkServices::Application exists as a catch-all enum case. An integrator could use Application:… ORNs instead of custom string prefixes, but every integrator would share one prefix and therefore one serviceFormat() validator — strong per-service ORN validation is not possible. Custom string prefixes are preferred so each integrator can register its own claim/requirement classes and proviso layout.

Usage

Examples below assume amtgard/ork-iam-orn-definitions is installed. Adjust namespaces if you use custom definition classes.

Single claim

<?php
require __DIR__ . '/vendor/autoload.php';

use Amtgard\IAM\ClaimFactory;
use Amtgard\IAM\Definitions\ORN\AttendanceRequirement;
use Amtgard\IAM\Definitions\ORN\AttendanceClaim;
use Amtgard\IAM\OrkServices;
use Amtgard\IAM\Resource;

// Create a Claim instance from an ORN string
$claim = ClaimFactory::createOrn('Attendance:*::::::ORK/AddAttendance'); // => AttendanceClaim

// Define a Requirement for Attendance on the same ORN pattern
$requirement = new AttendanceRequirement(OrkServices::Attendance, 'Attendance:1:2:3:4:5:6:ORK/AddAttendance');

// Evaluate permission
if ($requirement->allows($claim)) {
    // The claim satisfies the requirement
}

Policy

use Amtgard\IAM\Allowance\Policy;
use Amtgard\IAM\Definitions\ORN\OrkClaim;
use Amtgard\IAM\Definitions\ORN\OrkRequirement;
use Amtgard\IAM\OrkServices;

$claim1 = new OrkClaim(OrkServices::ORK, "ORK:1:::::*");
$claim2 = new OrkClaim(OrkServices::ORK, "ORK:2:::::*");
$claim3 = new OrkClaim(OrkServices::ORK, "ORK::3::::*");
$claim4 = new OrkClaim(OrkServices::ORK, "ORK:::::4:*");

$policy = new Policy([$claim1, $claim2, $claim3, $claim4]);
$requirement = new OrkRequirement(OrkServices::ORK, "ORK:1:7:8:9:10:ORK/AddKingdom");

if ($policy->isAuthorized($requirement)) {
    // Policy satisfies the requirement
}

Claim and policy composition (v2.1.0)

Build claims fluently instead of hand-authoring ORN strings:

use Amtgard\IAM\Allowance\ClaimBuilder;
use Amtgard\IAM\Catalog\ServiceCatalog;

$claim = ClaimBuilder::forPrefix(ServiceCatalog::Attendance)
    ->segment(ServiceCatalog::Configuration, 1)
    ->segment(ServiceCatalog::Kingdom, 42)
    ->resource('ORK', 'AddAttendance')
    ->build();

Compose policies from ORN lines or claims; merge dedupes by canonical ORN string:

use Amtgard\IAM\Allowance\PolicyBuilder;

$policy = PolicyBuilder::create()
    ->addOrn('ORK:1:::::*')
    ->addClaim($claim)
    ->build();

$combined = PolicyBuilder::from($policyA)->merge($policyB)->build();

PolicyFactory::fromOrn() remains available and delegates to PolicyBuilder internally.

IDP / JWT integration

After JWT signature verification, build the effective policy from signed claims — do not merge untrusted partial policies client-side:

use Amtgard\IAM\Allowance\PolicyDocument;

$doc = PolicyDocument::fromVerifiedJwt($verifiedPayload);
$policy = $doc->policy();

if ($policy->isAuthorized($requirement)) {
    // authorized
}

$blob = $doc->integratorDocument(); // optional opaque integrator config; not used by isAuthorized()

Expected JWT payload shape:

Field Type Description
policy_lines string[] ORN lines (global + integrator-specific), all ORK-namespace
integrator_document array (optional) Application-defined blob; exposed via getter only

PolicyDocument::fromOrnList(), fromJson(), and fromVerifiedPayload() are also available for tests and server-side assembly of trusted fragments.

Upgrading from 1.4? See docs/MIGRATION-2.0.md.

Service identifiers

OrkServices enumerates known service names used in ORN provisos and registration. These are identifiers within the IAM model — not all have ORN definition classes yet.

ORK services

  • ORK
  • Configuration
  • Mundane
  • Attendance
  • Kingdom
  • Park
  • Unit
  • Game
  • Event
  • EventInstance
  • Awards
  • Audit
  • Cache
  • Tenant
  • Officer
  • Recommendations
  • Tournament

Planned applications

  • Idp
  • Documents
  • Forums
  • Media
  • Errata

ORN definition classes for additional services will be added in amtgard/ork-iam-orn-definitions (or your own registration) as schemas are finalized.

Testing

Run the test suite:

vendor/bin/phpunit

Run with code coverage:

XDEBUG_MODE=coverage vendor/bin/phpunit -c phpunit.coverage.xml.dist --coverage-text

amtgard/ork-iam 适用场景与选型建议

amtgard/ork-iam 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 28 次下载、GitHub Stars 达 0, 最近一次更新时间为 2025 年 09 月 23 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 amtgard/ork-iam 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 amtgard/ork-iam 我们能提供哪些服务?
定制开发 / 二次开发

基于 amtgard/ork-iam 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 28
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 19
  • 依赖项目数: 2
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-09-23