Add Keto service + migrate (todo §3); OPL role/group/resource namespaces, fine-grained resource permits
This commit is contained in:
19
ory/keto/keto.yml
Normal file
19
ory/keto/keto.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
# Ory Keto — authorization (ReBAC), the source of truth for roles/groups and the rare
|
||||
# fine-grained check (README: three tiers of "may I?"). The permission model lives in
|
||||
# namespaces.keto.ts (OPL); DSN comes from the env (the per-service keto DB). The web
|
||||
# app never connects directly — it calls the read (4466) / write (4467) APIs, the ports
|
||||
# config.ts points at.
|
||||
namespaces:
|
||||
location: file:///etc/config/keto/namespaces.keto.ts
|
||||
|
||||
serve:
|
||||
read:
|
||||
host: 0.0.0.0
|
||||
port: 4466
|
||||
write:
|
||||
host: 0.0.0.0
|
||||
port: 4467
|
||||
|
||||
log:
|
||||
level: info
|
||||
format: text
|
||||
47
ory/keto/namespaces.keto.ts
Normal file
47
ory/keto/namespaces.keto.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
// Ory Permission Language (OPL) — the authorization model Keto enforces. Keto parses
|
||||
// this file (referenced by keto.yml `namespaces.location`); the `@ory/keto-namespace-types`
|
||||
// import is for the author's editor only and is ignored at load. Subject ids are Kratos
|
||||
// identity ids (== the JWT `sub`).
|
||||
import { Context, Namespace, SubjectSet } from "@ory/keto-namespace-types"
|
||||
|
||||
// A human identity. Subjects are written as `user:<kratos-identity-id>`.
|
||||
class User implements Namespace {}
|
||||
|
||||
// A subject set: a named collection of users (and nested groups), resolved transitively.
|
||||
// The admin "Groups" screen (§5) manages membership; checks expand it automatically.
|
||||
class Group implements Namespace {
|
||||
related: {
|
||||
members: (User | SubjectSet<Group, "members">)[]
|
||||
}
|
||||
}
|
||||
|
||||
// A coarse role — the source of truth for the JWT `roles` claim. At login the app reads
|
||||
// `role:<name>#members@user:<id>` from Keto and projects the result into the token
|
||||
// (README: Login → session JWT). A group can hold a role, so members can be users or groups.
|
||||
class Role implements Namespace {
|
||||
related: {
|
||||
members: (User | SubjectSet<Group, "members">)[]
|
||||
}
|
||||
}
|
||||
|
||||
// A fine-grained, relationship-checked resource — README's third "may I?" tier, the rare
|
||||
// live Keto check (e.g. sharing/delegation). Permissions nest: owner ⊇ editor ⊇ viewer.
|
||||
// Grants accept a user directly or any member of a group.
|
||||
class Resource implements Namespace {
|
||||
related: {
|
||||
owners: (User | SubjectSet<Group, "members">)[]
|
||||
editors: (User | SubjectSet<Group, "members">)[]
|
||||
viewers: (User | SubjectSet<Group, "members">)[]
|
||||
}
|
||||
|
||||
permits = {
|
||||
view: (ctx: Context): boolean =>
|
||||
this.related.viewers.includes(ctx.subject) ||
|
||||
this.related.editors.includes(ctx.subject) ||
|
||||
this.related.owners.includes(ctx.subject),
|
||||
edit: (ctx: Context): boolean =>
|
||||
this.related.editors.includes(ctx.subject) ||
|
||||
this.related.owners.includes(ctx.subject),
|
||||
delete: (ctx: Context): boolean => this.related.owners.includes(ctx.subject),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user