Initial import of verae-nats-accounts from zapier monorepo
This commit is contained in:
commit
358f7399c9
7 changed files with 103 additions and 0 deletions
3
NATS.md
Normal file
3
NATS.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# NATS — verae-nats-accounts
|
||||
|
||||
Not a subscriber. Defines INTERNAL vs LEAF. Leaf deny `verae.billing.>`.
|
||||
8
README.md
Normal file
8
README.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# verae-nats-accounts
|
||||
|
||||
NATS **account + leaf allow-list**. Leaf nodes cannot publish `verae.billing.*`.
|
||||
|
||||
**Forgejo:** https://git.georgelambert.org/marchon/verae-nats-accounts
|
||||
|
||||
- `policy.json` — machine-readable allow/deny (used by access-leaf).
|
||||
- `nats.conf` — sketch for a future accounts-enabled nats-server (loopback).
|
||||
21
nats.conf
Normal file
21
nats.conf
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# Lab accounts sketch. Loopback only. Do not publish 4222.
|
||||
# INTERNAL: middleware, account-balance, authz, identity.
|
||||
# LEAF: access-leaf and remote leaf nodes — no billing.
|
||||
|
||||
listen: 127.0.0.1:4222
|
||||
http: 127.0.0.1:8222
|
||||
jetstream {}
|
||||
|
||||
accounts {
|
||||
INTERNAL {
|
||||
users = [ { user: internal, password: internal-dev } ]
|
||||
jetstream: enabled
|
||||
}
|
||||
LEAF {
|
||||
users = [ { user: leaf, password: leaf-dev } ]
|
||||
exports = []
|
||||
imports = []
|
||||
}
|
||||
}
|
||||
# Subject restrictions for LEAF are enforced in policy.json + access-leaf
|
||||
# until this nats-server is started with full auth callout.
|
||||
10
package.json
Normal file
10
package.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "verae-nats-accounts",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"description": "NATS account and leaf subject policy (INTERNAL vs LEAF)",
|
||||
"scripts": {
|
||||
"test": "node --test test/*.test.js"
|
||||
}
|
||||
}
|
||||
35
policy.json
Normal file
35
policy.json
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"accounts": {
|
||||
"INTERNAL": {
|
||||
"publish": [">"],
|
||||
"subscribe": [">"]
|
||||
},
|
||||
"LEAF": {
|
||||
"publish": [
|
||||
"verae.access.leaf.in",
|
||||
"verae.archive.put",
|
||||
"verae.archive.query",
|
||||
"verae.archive.reply.*",
|
||||
"verae.zapier.jobs.watch",
|
||||
"verae.zapier.jobs.events",
|
||||
"verae.zapier.webhooks.deliver"
|
||||
],
|
||||
"subscribe": [
|
||||
"verae.access.leaf.in",
|
||||
"verae.archive.>",
|
||||
"verae.zapier.jobs.>",
|
||||
"verae.zapier.webhooks.deliver"
|
||||
],
|
||||
"deny_publish": ["verae.billing.>", "verae.access.authz.>"],
|
||||
"deny_subscribe": ["verae.billing.>"]
|
||||
}
|
||||
},
|
||||
"leafAllow": [
|
||||
"verae.archive.put",
|
||||
"verae.archive.query",
|
||||
"verae.archive.reply.",
|
||||
"verae.zapier.jobs.watch",
|
||||
"verae.zapier.jobs.events",
|
||||
"verae.zapier.webhooks.deliver"
|
||||
]
|
||||
}
|
||||
14
src/policy.js
Normal file
14
src/policy.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const FILE = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'policy.json');
|
||||
|
||||
export function loadPolicy() {
|
||||
return JSON.parse(fs.readFileSync(FILE, 'utf8'));
|
||||
}
|
||||
|
||||
export function leafAllowed(subject) {
|
||||
const allow = loadPolicy().leafAllow || [];
|
||||
return allow.some((p) => (p.endsWith('.') ? subject.startsWith(p) : subject === p || subject.startsWith(`${p}.`)));
|
||||
}
|
||||
12
test/policy.test.js
Normal file
12
test/policy.test.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { leafAllowed, loadPolicy } from '../src/policy.js';
|
||||
|
||||
test('leaf may archive and jobs, never billing', () => {
|
||||
assert.equal(leafAllowed('verae.archive.put'), true);
|
||||
assert.equal(leafAllowed('verae.archive.reply.abc'), true);
|
||||
assert.equal(leafAllowed('verae.zapier.jobs.watch'), true);
|
||||
assert.equal(leafAllowed('verae.billing.balance.adjust'), false);
|
||||
assert.equal(leafAllowed('verae.billing.statement.get'), false);
|
||||
assert.ok(loadPolicy().accounts.LEAF.deny_publish.includes('verae.billing.>'));
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue