Implement managed browser security, individual agents and observability
This commit is contained in:
1 parent
ff482ebe23
commit
ea448de2d4
172 files changed
+5404
-347
No files matched your search
@@ -0,0 +1,47 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import grants from '../apps/browser/agent-grants.cjs';
|
||||
const now=Date.now(),expiry=new Date(now+60000).toISOString();
|
||||
const policy=()=>({expiresAt:expiry,agents:{enabled:true,identityMode:'individual',scopes:['read','navigate'],allowedHosts:['corp.example'],grants:[{id:'worker.a',name:'Reader',enabled:true,expiresAt:expiry,scopes:['read'],allowedHosts:['corp.example'],generation:2}]}});
|
||||
const authorize=changes=>grants.authorizeGrant({policy:policy(),ready:true,principalId:'worker.a',generation:2,action:'read',url:'https://corp.example/',hostMatches:(a,b)=>a===b,now,...changes});
|
||||
test('active grant discovery excludes expired and disabled grants and exposes no mutable policy reference',()=>{
|
||||
const p=policy();p.agents.grants.push({...p.agents.grants[0],id:'disabled',enabled:false},{...p.agents.grants[0],id:'expired',expiresAt:new Date(now-1).toISOString()});
|
||||
const active=grants.activeGrants(p,now);assert.deepEqual(active.map(g=>g.id),['worker.a']);active[0].scopes.push('navigate');assert.deepEqual(p.agents.grants[0].scopes,['read']);
|
||||
assert.deepEqual(grants.activeGrants(p,now+60001),[]);
|
||||
});
|
||||
test('individual authorization intersects global and principal rights and destinations',()=>{
|
||||
assert.equal(authorize().allowed,true);
|
||||
for(const changes of [{principalId:'worker.b'},{generation:1},{action:'navigate'},{ready:false},{url:'https://evil.example/'},{url:'file:///secret'},{now:now+60001}])assert.equal(authorize(changes).allowed,false);
|
||||
const p=policy();p.agents.scopes=[];assert.equal(authorize({policy:p}).allowed,false);
|
||||
p.agents.scopes=['read'];p.agents.grants[0].scopes=[];assert.equal(authorize({policy:p}).allowed,false);
|
||||
p.agents.grants[0].scopes=['read'];p.agents.grants[0].allowedHosts=['other.example'];assert.equal(authorize({policy:p}).allowed,false);
|
||||
});
|
||||
test('legacy mode never accepts individual credentials and individual mode has no shared bypass',()=>{
|
||||
assert.equal(authorize({principalId:undefined,generation:undefined}).allowed,false);
|
||||
const p=policy();p.agents.identityMode='legacy';assert.equal(authorize({policy:p}).allowed,false);
|
||||
assert.equal(authorize({policy:p,principalId:undefined,generation:undefined}).allowed,true);
|
||||
delete p.agents.identityMode;assert.equal(authorize({policy:p,principalId:undefined,generation:undefined}).allowed,false);
|
||||
});
|
||||
test('generation floor survives removal and restart and disables restored older credentials',()=>{
|
||||
const first=grants.reconcileGenerationFloor(policy().agents.grants,{});
|
||||
const removed=grants.reconcileGenerationFloor([],JSON.parse(JSON.stringify(first.floor)));
|
||||
const restored=grants.reconcileGenerationFloor([{...policy().agents.grants[0],generation:1}],removed.floor);
|
||||
assert.equal(restored.grants[0].enabled,false);assert.equal(restored.floor['worker.a'],2);
|
||||
assert.equal(grants.reconcileGenerationFloor([{...policy().agents.grants[0],generation:3}],restored.floor).grants[0].enabled,true);
|
||||
});
|
||||
test('protected credential publication is atomic, bounded to hashed names and stale-safe',async()=>{
|
||||
const dir=fs.mkdtempSync(path.join(os.tmpdir(),'agent-grants-'));
|
||||
try{
|
||||
const filePath=grants.descriptorPath(dir,'worker.a');assert.match(path.basename(filePath),/^agent-[a-f0-9]{64}\.json$/);
|
||||
await grants.persistConnection({filePath,connection:{token:'synthetic-secret'},protect:async()=> 'opaque-dpapi',isCurrent:()=>true});
|
||||
const prior=fs.readFileSync(filePath,'utf8');assert.equal(prior.includes('synthetic-secret'),false);
|
||||
let current=true;
|
||||
await assert.rejects(grants.persistConnection({filePath,connection:{token:'other'},protect:async()=>{current=false;return 'new';},isCurrent:()=>current}),/context changed/);
|
||||
assert.equal(fs.readFileSync(filePath,'utf8'),prior);assert.equal(fs.readdirSync(dir).length,1);
|
||||
const linked=path.join(dir,'linked.json');fs.linkSync(filePath,linked);
|
||||
await assert.rejects(grants.persistConnection({filePath,connection:{},protect:async()=>'',isCurrent:()=>true}),/Unsafe credential/);
|
||||
}finally{fs.rmSync(dir,{recursive:true,force:true});}
|
||||
});
|
||||
Reference in new issue
Block a user