@mondaydotcomorg/atp-provenance 0.18.4-rc.1 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -1
- package/dist/__tests__/declarative-policy.test.d.ts +2 -0
- package/dist/__tests__/declarative-policy.test.d.ts.map +1 -0
- package/dist/__tests__/declarative-policy.test.js +109 -0
- package/dist/__tests__/declarative-policy.test.js.map +1 -0
- package/dist/__tests__/dynamic-policy.test.d.ts +2 -0
- package/dist/__tests__/dynamic-policy.test.d.ts.map +1 -0
- package/dist/__tests__/dynamic-policy.test.js +49 -0
- package/dist/__tests__/dynamic-policy.test.js.map +1 -0
- package/dist/declarative-policy.d.ts +47 -0
- package/dist/declarative-policy.d.ts.map +1 -0
- package/dist/declarative-policy.js +164 -0
- package/dist/declarative-policy.js.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/policies/__tests__/declarative.test.d.ts +2 -0
- package/dist/policies/__tests__/declarative.test.d.ts.map +1 -0
- package/dist/policies/__tests__/declarative.test.js +109 -0
- package/dist/policies/__tests__/declarative.test.js.map +1 -0
- package/dist/policies/builder.d.ts +36 -0
- package/dist/policies/builder.d.ts.map +1 -0
- package/dist/policies/builder.js +77 -0
- package/dist/policies/builder.js.map +1 -0
- package/dist/policies/declarative.d.ts +47 -0
- package/dist/policies/declarative.d.ts.map +1 -0
- package/dist/policies/declarative.js +170 -0
- package/dist/policies/declarative.js.map +1 -0
- package/dist/policies/dynamic.d.ts +39 -0
- package/dist/policies/dynamic.d.ts.map +1 -0
- package/dist/policies/dynamic.js +75 -0
- package/dist/policies/dynamic.js.map +1 -0
- package/dist/policies/schema.d.ts +270 -0
- package/dist/policies/schema.d.ts.map +1 -0
- package/dist/policies/schema.js +42 -0
- package/dist/policies/schema.js.map +1 -0
- package/dist/registry.d.ts +15 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +73 -0
- package/dist/registry.js.map +1 -1
- package/dist/store.d.ts +53 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +78 -0
- package/dist/store.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { createDeclarativePolicy } from '../declarative.js';
|
|
2
|
+
import { createProvenanceProxy, setGlobalProvenanceStore } from '../../registry.js';
|
|
3
|
+
import { ProvenanceSource } from '../../types.js';
|
|
4
|
+
import { InMemoryProvenanceStore } from '../../store.js';
|
|
5
|
+
describe('Declarative Policies', () => {
|
|
6
|
+
beforeAll(() => {
|
|
7
|
+
setGlobalProvenanceStore(new InMemoryProvenanceStore());
|
|
8
|
+
});
|
|
9
|
+
const userSource = {
|
|
10
|
+
type: ProvenanceSource.USER,
|
|
11
|
+
timestamp: Date.now(),
|
|
12
|
+
};
|
|
13
|
+
const toolSource = {
|
|
14
|
+
type: ProvenanceSource.TOOL,
|
|
15
|
+
toolName: 'getUser',
|
|
16
|
+
apiGroup: 'users',
|
|
17
|
+
timestamp: Date.now(),
|
|
18
|
+
};
|
|
19
|
+
const policyConfig = {
|
|
20
|
+
id: 'test-policy',
|
|
21
|
+
scope: {
|
|
22
|
+
toolName: 'send',
|
|
23
|
+
},
|
|
24
|
+
rules: [
|
|
25
|
+
{
|
|
26
|
+
id: 'block-external-user-data',
|
|
27
|
+
action: 'block',
|
|
28
|
+
conditions: [
|
|
29
|
+
{
|
|
30
|
+
field: 'args.to',
|
|
31
|
+
operator: 'notEndsWith',
|
|
32
|
+
value: '@company.com',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
field: 'provenance.args.body.source.type',
|
|
36
|
+
operator: 'equals',
|
|
37
|
+
value: 'user',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
reason: 'Cannot send user data to external email',
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
const policy = createDeclarativePolicy(policyConfig);
|
|
45
|
+
it('should ignore calls outside of scope', async () => {
|
|
46
|
+
const result = await policy.check('otherTool', { to: 'external@gmail.com' }, () => null);
|
|
47
|
+
expect(result.action).toBe('log'); // Default allow
|
|
48
|
+
});
|
|
49
|
+
it('should block when conditions match', async () => {
|
|
50
|
+
const userData = createProvenanceProxy({ data: 'sensitive' }, userSource);
|
|
51
|
+
const { getProvenance } = await import('../../registry.js');
|
|
52
|
+
const result = await policy.check('send', {
|
|
53
|
+
to: 'attacker@evil.com',
|
|
54
|
+
body: userData,
|
|
55
|
+
}, getProvenance);
|
|
56
|
+
expect(result.action).toBe('block');
|
|
57
|
+
expect(result.reason).toBe('Cannot send user data to external email');
|
|
58
|
+
});
|
|
59
|
+
it('should allow when conditions do not match (email is internal)', async () => {
|
|
60
|
+
const userData = createProvenanceProxy({ data: 'sensitive' }, userSource);
|
|
61
|
+
const { getProvenance } = await import('../../registry.js');
|
|
62
|
+
const result = await policy.check('send', {
|
|
63
|
+
to: 'alice@company.com',
|
|
64
|
+
body: userData,
|
|
65
|
+
}, getProvenance);
|
|
66
|
+
expect(result.action).toBe('log'); // Default allow
|
|
67
|
+
});
|
|
68
|
+
it('should allow when conditions do not match (data is not user source)', async () => {
|
|
69
|
+
const toolData = createProvenanceProxy({ data: 'public info' }, toolSource);
|
|
70
|
+
const { getProvenance } = await import('../../registry.js');
|
|
71
|
+
const result = await policy.check('send', {
|
|
72
|
+
to: 'attacker@evil.com',
|
|
73
|
+
body: toolData,
|
|
74
|
+
}, getProvenance);
|
|
75
|
+
expect(result.action).toBe('log'); // Default allow
|
|
76
|
+
});
|
|
77
|
+
it('should handle nested provenance paths', async () => {
|
|
78
|
+
const complexPolicyConfig = {
|
|
79
|
+
id: 'nested-test',
|
|
80
|
+
scope: { toolName: 'update' },
|
|
81
|
+
rules: [
|
|
82
|
+
{
|
|
83
|
+
action: 'block',
|
|
84
|
+
conditions: [
|
|
85
|
+
{
|
|
86
|
+
field: 'provenance.args.user.profile.email.source.type',
|
|
87
|
+
operator: 'equals',
|
|
88
|
+
value: 'user',
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
};
|
|
94
|
+
const complexPolicy = createDeclarativePolicy(complexPolicyConfig);
|
|
95
|
+
const { getProvenance } = await import('../../registry.js');
|
|
96
|
+
// Create a user object where the nested properties have provenance
|
|
97
|
+
const user = createProvenanceProxy({
|
|
98
|
+
profile: {
|
|
99
|
+
email: 'test@test.com',
|
|
100
|
+
},
|
|
101
|
+
}, userSource);
|
|
102
|
+
const args = {
|
|
103
|
+
user,
|
|
104
|
+
};
|
|
105
|
+
const result = await complexPolicy.check('update', args, getProvenance);
|
|
106
|
+
expect(result.action).toBe('block');
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
//# sourceMappingURL=declarative.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"declarative.test.js","sourceRoot":"","sources":["../../../src/policies/__tests__/declarative.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { DeclarativePolicyConfig, PolicyRule, Operator } from './declarative.js';
|
|
2
|
+
import type { PolicyAction } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Helper class to build policy rules fluently
|
|
5
|
+
*/
|
|
6
|
+
export declare class RuleBuilder {
|
|
7
|
+
private rule;
|
|
8
|
+
constructor(action?: PolicyAction);
|
|
9
|
+
action(action: PolicyAction): this;
|
|
10
|
+
id(id: string): this;
|
|
11
|
+
reason(reason: string): this;
|
|
12
|
+
condition(field: string, operator: Operator, value: any): this;
|
|
13
|
+
build(): PolicyRule;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Helper class to build declarative policies fluently
|
|
17
|
+
*/
|
|
18
|
+
export declare class PolicyBuilder {
|
|
19
|
+
private config;
|
|
20
|
+
constructor(id: string);
|
|
21
|
+
description(desc: string): this;
|
|
22
|
+
scopeTool(toolNamePattern: string): this;
|
|
23
|
+
scopeApiGroup(apiGroupPattern: string): this;
|
|
24
|
+
/**
|
|
25
|
+
* Add a rule using a builder callback
|
|
26
|
+
* @example
|
|
27
|
+
* .addRule(r => r.action('block').condition('args.amount', 'matches', '>1000'))
|
|
28
|
+
*/
|
|
29
|
+
addRule(buildFn: (builder: RuleBuilder) => RuleBuilder): this;
|
|
30
|
+
/**
|
|
31
|
+
* Add a fully formed rule object
|
|
32
|
+
*/
|
|
33
|
+
addRuleObject(rule: PolicyRule): this;
|
|
34
|
+
build(): DeclarativePolicyConfig;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/policies/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACtF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;GAEG;AACH,qBAAa,WAAW;IACvB,OAAO,CAAC,IAAI,CAGV;gBAEU,MAAM,GAAE,YAAoB;IAIxC,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAKlC,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAKpB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK5B,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAK9D,KAAK,IAAI,UAAU;CAGnB;AAED;;GAEG;AACH,qBAAa,aAAa;IACzB,OAAO,CAAC,MAAM,CAA0B;gBAE5B,EAAE,EAAE,MAAM;IAQtB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK/B,SAAS,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI;IAKxC,aAAa,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI;IAK5C;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,WAAW,GAAG,IAAI;IAM7D;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAKrC,KAAK,IAAI,uBAAuB;CAGhC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper class to build policy rules fluently
|
|
3
|
+
*/
|
|
4
|
+
export class RuleBuilder {
|
|
5
|
+
rule = {
|
|
6
|
+
action: 'log',
|
|
7
|
+
conditions: [],
|
|
8
|
+
};
|
|
9
|
+
constructor(action = 'log') {
|
|
10
|
+
this.rule.action = action;
|
|
11
|
+
}
|
|
12
|
+
action(action) {
|
|
13
|
+
this.rule.action = action;
|
|
14
|
+
return this;
|
|
15
|
+
}
|
|
16
|
+
id(id) {
|
|
17
|
+
this.rule.id = id;
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
reason(reason) {
|
|
21
|
+
this.rule.reason = reason;
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
condition(field, operator, value) {
|
|
25
|
+
this.rule.conditions.push({ field, operator, value });
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
build() {
|
|
29
|
+
return this.rule;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Helper class to build declarative policies fluently
|
|
34
|
+
*/
|
|
35
|
+
export class PolicyBuilder {
|
|
36
|
+
config;
|
|
37
|
+
constructor(id) {
|
|
38
|
+
this.config = {
|
|
39
|
+
id,
|
|
40
|
+
scope: {},
|
|
41
|
+
rules: [],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
description(desc) {
|
|
45
|
+
this.config.description = desc;
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
scopeTool(toolNamePattern) {
|
|
49
|
+
this.config.scope.toolName = toolNamePattern;
|
|
50
|
+
return this;
|
|
51
|
+
}
|
|
52
|
+
scopeApiGroup(apiGroupPattern) {
|
|
53
|
+
this.config.scope.apiGroup = apiGroupPattern;
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Add a rule using a builder callback
|
|
58
|
+
* @example
|
|
59
|
+
* .addRule(r => r.action('block').condition('args.amount', 'matches', '>1000'))
|
|
60
|
+
*/
|
|
61
|
+
addRule(buildFn) {
|
|
62
|
+
const builder = new RuleBuilder();
|
|
63
|
+
this.config.rules.push(buildFn(builder).build());
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Add a fully formed rule object
|
|
68
|
+
*/
|
|
69
|
+
addRuleObject(rule) {
|
|
70
|
+
this.config.rules.push(rule);
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
build() {
|
|
74
|
+
return this.config;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/policies/builder.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,OAAO,WAAW;IACf,IAAI,GAAe;QAC1B,MAAM,EAAE,KAAK;QACb,UAAU,EAAE,EAAE;KACd,CAAC;IAEF,YAAY,SAAuB,KAAK;QACvC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,MAAoB;QAC1B,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAC1B,OAAO,IAAI,CAAC;IACb,CAAC;IAED,EAAE,CAAC,EAAU;QACZ,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,CAAC,MAAc;QACpB,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAC1B,OAAO,IAAI,CAAC;IACb,CAAC;IAED,SAAS,CAAC,KAAa,EAAE,QAAkB,EAAE,KAAU;QACtD,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC;IACb,CAAC;IAED,KAAK;QACJ,OAAO,IAAI,CAAC,IAAI,CAAC;IAClB,CAAC;CACD;AAED;;GAEG;AACH,MAAM,OAAO,aAAa;IACjB,MAAM,CAA0B;IAExC,YAAY,EAAU;QACrB,IAAI,CAAC,MAAM,GAAG;YACb,EAAE;YACF,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,EAAE;SACT,CAAC;IACH,CAAC;IAED,WAAW,CAAC,IAAY;QACvB,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC;QAC/B,OAAO,IAAI,CAAC;IACb,CAAC;IAED,SAAS,CAAC,eAAuB;QAChC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,eAAe,CAAC;QAC7C,OAAO,IAAI,CAAC;IACb,CAAC;IAED,aAAa,CAAC,eAAuB;QACpC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,eAAe,CAAC;QAC7C,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,OAA8C;QACrD,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,IAAgB;QAC7B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IACb,CAAC;IAED,KAAK;QACJ,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;CACD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { SecurityPolicy, PolicyAction } from '../types.js';
|
|
2
|
+
export type Operator = 'equals' | 'notEquals' | 'contains' | 'notContains' | 'startsWith' | 'notStartsWith' | 'endsWith' | 'notEndsWith' | 'matches' | 'in' | 'notIn';
|
|
3
|
+
export interface Condition {
|
|
4
|
+
/**
|
|
5
|
+
* Field to check.
|
|
6
|
+
* - "args.paramName": Value of a tool argument
|
|
7
|
+
* - "provenance.args.paramName.source.type": Provenance metadata
|
|
8
|
+
* - "provenance.args.paramName.readers": Reader permissions
|
|
9
|
+
*/
|
|
10
|
+
field: string;
|
|
11
|
+
operator: Operator;
|
|
12
|
+
value: any;
|
|
13
|
+
}
|
|
14
|
+
export interface PolicyRule {
|
|
15
|
+
id?: string;
|
|
16
|
+
/** Action to take if conditions match */
|
|
17
|
+
action: PolicyAction;
|
|
18
|
+
/** Conditions (implicit AND) - all must match for the rule to trigger */
|
|
19
|
+
conditions: Condition[];
|
|
20
|
+
/** Custom reason message */
|
|
21
|
+
reason?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface DeclarativePolicyConfig {
|
|
24
|
+
id: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
scope: {
|
|
27
|
+
/** Regex pattern or exact match for tool name */
|
|
28
|
+
toolName?: string;
|
|
29
|
+
/** Regex pattern or exact match for API group */
|
|
30
|
+
apiGroup?: string;
|
|
31
|
+
};
|
|
32
|
+
/** Rules are evaluated in order. First match wins. */
|
|
33
|
+
rules: PolicyRule[];
|
|
34
|
+
}
|
|
35
|
+
export interface PolicyConfiguration {
|
|
36
|
+
version: string;
|
|
37
|
+
policies: DeclarativePolicyConfig[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Create a SecurityPolicy from a declarative configuration
|
|
41
|
+
*/
|
|
42
|
+
export declare function createDeclarativePolicy(config: DeclarativePolicyConfig): SecurityPolicy;
|
|
43
|
+
/**
|
|
44
|
+
* Load policies from a full configuration object or array of policy configs
|
|
45
|
+
*/
|
|
46
|
+
export declare function loadDeclarativePolicies(config: PolicyConfiguration | DeclarativePolicyConfig[]): SecurityPolicy[];
|
|
47
|
+
//# sourceMappingURL=declarative.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"declarative.d.ts","sourceRoot":"","sources":["../../src/policies/declarative.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAoC,YAAY,EAAE,MAAM,aAAa,CAAC;AAElG,MAAM,MAAM,QAAQ,GACjB,QAAQ,GACR,WAAW,GACX,UAAU,GACV,aAAa,GACb,YAAY,GACZ,eAAe,GACf,UAAU,GACV,aAAa,GACb,SAAS,GACT,IAAI,GACJ,OAAO,CAAC;AAEX,MAAM,WAAW,SAAS;IACzB;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,GAAG,CAAC;CACX;AAED,MAAM,WAAW,UAAU;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,MAAM,EAAE,YAAY,CAAC;IACrB,yEAAyE;IACzE,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,uBAAuB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE;QACN,iDAAiD;QACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,iDAAiD;QACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,sDAAsD;IACtD,KAAK,EAAE,UAAU,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,uBAAuB,EAAE,CAAC;CACpC;AAuID;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,uBAAuB,GAAG,cAAc,CAyCvF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,mBAAmB,GAAG,uBAAuB,EAAE,GACrD,cAAc,EAAE,CAKlB"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a value from a path in the arguments or provenance
|
|
3
|
+
*/
|
|
4
|
+
function resolveValue(path, args, getProvenance) {
|
|
5
|
+
const parts = path.split('.');
|
|
6
|
+
const root = parts.shift();
|
|
7
|
+
if (root === 'args') {
|
|
8
|
+
let current = args;
|
|
9
|
+
for (const part of parts) {
|
|
10
|
+
if (current === null || current === undefined) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
current = current[part];
|
|
14
|
+
}
|
|
15
|
+
return current;
|
|
16
|
+
}
|
|
17
|
+
if (root === 'provenance' && parts[0] === 'args') {
|
|
18
|
+
parts.shift(); // remove 'args'
|
|
19
|
+
const argName = parts.shift(); // get argument name
|
|
20
|
+
if (!argName)
|
|
21
|
+
return undefined;
|
|
22
|
+
const argValue = args[argName];
|
|
23
|
+
// Better approach:
|
|
24
|
+
// 1. Traverse args until we find the object.
|
|
25
|
+
// 2. Get provenance of that object.
|
|
26
|
+
// 3. Traverse provenance metadata.
|
|
27
|
+
let remainingParts = [...parts];
|
|
28
|
+
// We don't know where the split is.
|
|
29
|
+
// Let's try to find standard metadata keys in the path.
|
|
30
|
+
const metadataKeys = ['source', 'readers', 'dependencies', 'id', 'context'];
|
|
31
|
+
let splitIndex = -1;
|
|
32
|
+
for (let i = 0; i < remainingParts.length; i++) {
|
|
33
|
+
if (metadataKeys.includes(remainingParts[i])) {
|
|
34
|
+
splitIndex = i;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (splitIndex === -1) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
// Traverse to the value that should have provenance
|
|
42
|
+
let valuePath = remainingParts.slice(0, splitIndex);
|
|
43
|
+
let metaPath = remainingParts.slice(splitIndex);
|
|
44
|
+
let currentVal = argValue;
|
|
45
|
+
for (const part of valuePath) {
|
|
46
|
+
if (currentVal === null || currentVal === undefined)
|
|
47
|
+
return undefined;
|
|
48
|
+
currentVal = currentVal[part];
|
|
49
|
+
}
|
|
50
|
+
const metadata = getProvenance(currentVal);
|
|
51
|
+
if (!metadata)
|
|
52
|
+
return undefined;
|
|
53
|
+
// Now traverse metadata
|
|
54
|
+
let currentMeta = metadata;
|
|
55
|
+
for (const part of metaPath) {
|
|
56
|
+
if (currentMeta === null || currentMeta === undefined)
|
|
57
|
+
return undefined;
|
|
58
|
+
currentMeta = currentMeta[part];
|
|
59
|
+
}
|
|
60
|
+
return currentMeta;
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
function evaluateCondition(actual, operator, expected) {
|
|
65
|
+
switch (operator) {
|
|
66
|
+
case 'equals':
|
|
67
|
+
return actual === expected;
|
|
68
|
+
case 'notEquals':
|
|
69
|
+
return actual !== expected;
|
|
70
|
+
case 'contains':
|
|
71
|
+
return Array.isArray(actual) || typeof actual === 'string'
|
|
72
|
+
? actual.includes(expected)
|
|
73
|
+
: false;
|
|
74
|
+
case 'notContains':
|
|
75
|
+
return Array.isArray(actual) || typeof actual === 'string'
|
|
76
|
+
? !actual.includes(expected)
|
|
77
|
+
: true;
|
|
78
|
+
case 'startsWith':
|
|
79
|
+
return typeof actual === 'string' ? actual.startsWith(expected) : false;
|
|
80
|
+
case 'notStartsWith':
|
|
81
|
+
return typeof actual === 'string' ? !actual.startsWith(expected) : true;
|
|
82
|
+
case 'endsWith':
|
|
83
|
+
return typeof actual === 'string' ? actual.endsWith(expected) : false;
|
|
84
|
+
case 'notEndsWith':
|
|
85
|
+
return typeof actual === 'string' ? !actual.endsWith(expected) : true;
|
|
86
|
+
case 'matches':
|
|
87
|
+
if (typeof actual === 'string') {
|
|
88
|
+
return new RegExp(expected).test(actual);
|
|
89
|
+
}
|
|
90
|
+
if (typeof actual === 'number' && typeof expected === 'string') {
|
|
91
|
+
const match = expected.match(/^([<>]=?|==|!=)(\d+(?:\.\d+)?)$/);
|
|
92
|
+
if (match) {
|
|
93
|
+
const [, op, value] = match;
|
|
94
|
+
const numValue = parseFloat(value);
|
|
95
|
+
switch (op) {
|
|
96
|
+
case '>':
|
|
97
|
+
return actual > numValue;
|
|
98
|
+
case '>=':
|
|
99
|
+
return actual >= numValue;
|
|
100
|
+
case '<':
|
|
101
|
+
return actual < numValue;
|
|
102
|
+
case '<=':
|
|
103
|
+
return actual <= numValue;
|
|
104
|
+
case '==':
|
|
105
|
+
return actual === numValue;
|
|
106
|
+
case '!=':
|
|
107
|
+
return actual !== numValue;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
112
|
+
case 'in':
|
|
113
|
+
return Array.isArray(expected) ? expected.includes(actual) : false;
|
|
114
|
+
case 'notIn':
|
|
115
|
+
return Array.isArray(expected) ? !expected.includes(actual) : true;
|
|
116
|
+
default:
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Create a SecurityPolicy from a declarative configuration
|
|
122
|
+
*/
|
|
123
|
+
export function createDeclarativePolicy(config) {
|
|
124
|
+
return {
|
|
125
|
+
name: config.id,
|
|
126
|
+
description: config.description,
|
|
127
|
+
check: async (toolName, args, getProvenance) => {
|
|
128
|
+
if (config.scope.toolName) {
|
|
129
|
+
const toolRegex = new RegExp(`^${config.scope.toolName}$`);
|
|
130
|
+
if (!toolRegex.test(toolName)) {
|
|
131
|
+
return { action: 'log' };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (config.scope.apiGroup) {
|
|
135
|
+
// Note: apiGroup is matched against the toolName prefix (e.g., "payment" from "payment.transfer")
|
|
136
|
+
// The SecurityPolicy interface doesn't receive apiGroup separately, but we can extract it from toolName
|
|
137
|
+
const extractedGroup = toolName.split('.')[0] || '';
|
|
138
|
+
const groupRegex = new RegExp(`^${config.scope.apiGroup}$`);
|
|
139
|
+
if (!groupRegex.test(extractedGroup)) {
|
|
140
|
+
return { action: 'log' };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
for (const rule of config.rules) {
|
|
144
|
+
const allMatch = rule.conditions.every((condition) => {
|
|
145
|
+
const actualValue = resolveValue(condition.field, args, getProvenance);
|
|
146
|
+
return evaluateCondition(actualValue, condition.operator, condition.value);
|
|
147
|
+
});
|
|
148
|
+
if (allMatch) {
|
|
149
|
+
return {
|
|
150
|
+
action: rule.action,
|
|
151
|
+
reason: rule.reason || `Matched rule ${rule.id || 'unknown'} in policy ${config.id}`,
|
|
152
|
+
policy: config.id,
|
|
153
|
+
context: { ruleId: rule.id, conditions: rule.conditions },
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return { action: 'log' };
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Load policies from a full configuration object or array of policy configs
|
|
163
|
+
*/
|
|
164
|
+
export function loadDeclarativePolicies(config) {
|
|
165
|
+
if (Array.isArray(config)) {
|
|
166
|
+
return config.map(createDeclarativePolicy);
|
|
167
|
+
}
|
|
168
|
+
return config.policies.map(createDeclarativePolicy);
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=declarative.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"declarative.js","sourceRoot":"","sources":["../../src/policies/declarative.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { SecurityPolicy, PolicyResult, ProvenanceMetadata } from '../types.js';
|
|
2
|
+
import { type DeclarativePolicyConfig } from './declarative.js';
|
|
3
|
+
/**
|
|
4
|
+
* A dynamic registry that manages multiple policies and acts as a single SecurityPolicy.
|
|
5
|
+
* This allows policies to be updated at runtime (e.g. from a UI or database) without restarting the server.
|
|
6
|
+
*/
|
|
7
|
+
export declare class DynamicPolicyRegistry implements SecurityPolicy {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
private policies;
|
|
11
|
+
constructor(initialPolicies?: SecurityPolicy[]);
|
|
12
|
+
/**
|
|
13
|
+
* Add or update a policy
|
|
14
|
+
*/
|
|
15
|
+
addPolicy(policy: SecurityPolicy): void;
|
|
16
|
+
/**
|
|
17
|
+
* Remove a policy by name
|
|
18
|
+
*/
|
|
19
|
+
removePolicy(name: string): void;
|
|
20
|
+
/**
|
|
21
|
+
* clear all policies
|
|
22
|
+
*/
|
|
23
|
+
clear(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Load policies from declarative configurations (JSON)
|
|
26
|
+
* This is useful for loading policies saved from a UI
|
|
27
|
+
*/
|
|
28
|
+
loadFromConfigs(configs: DeclarativePolicyConfig[], replace?: boolean): void;
|
|
29
|
+
/**
|
|
30
|
+
* Get all registered policies
|
|
31
|
+
*/
|
|
32
|
+
getPolicies(): SecurityPolicy[];
|
|
33
|
+
/**
|
|
34
|
+
* Implementation of the SecurityPolicy check interface.
|
|
35
|
+
* Delegates to all registered policies.
|
|
36
|
+
*/
|
|
37
|
+
check(toolName: string, args: Record<string, unknown>, getProvenance: (value: unknown) => ProvenanceMetadata | null): Promise<PolicyResult>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=dynamic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamic.d.ts","sourceRoot":"","sources":["../../src/policies/dynamic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACpF,OAAO,EAA2B,KAAK,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAEzF;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,cAAc;IAC3D,IAAI,SAA6B;IACjC,WAAW,SAAyD;IAEpE,OAAO,CAAC,QAAQ,CAA0C;gBAE9C,eAAe,GAAE,cAAc,EAAO;IAMlD;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAIvC;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIhC;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;;OAGG;IACH,eAAe,CAAC,OAAO,EAAE,uBAAuB,EAAE,EAAE,OAAO,UAAQ,GAAG,IAAI;IAU1E;;OAEG;IACH,WAAW,IAAI,cAAc,EAAE;IAI/B;;;OAGG;IACG,KAAK,CACV,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,kBAAkB,GAAG,IAAI,GAC1D,OAAO,CAAC,YAAY,CAAC;CAuBxB"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { createDeclarativePolicy } from './declarative.js';
|
|
2
|
+
/**
|
|
3
|
+
* A dynamic registry that manages multiple policies and acts as a single SecurityPolicy.
|
|
4
|
+
* This allows policies to be updated at runtime (e.g. from a UI or database) without restarting the server.
|
|
5
|
+
*/
|
|
6
|
+
export class DynamicPolicyRegistry {
|
|
7
|
+
name = 'dynamic-policy-registry';
|
|
8
|
+
description = 'Container for dynamically managed security policies';
|
|
9
|
+
policies = new Map();
|
|
10
|
+
constructor(initialPolicies = []) {
|
|
11
|
+
for (const policy of initialPolicies) {
|
|
12
|
+
this.policies.set(policy.name, policy);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Add or update a policy
|
|
17
|
+
*/
|
|
18
|
+
addPolicy(policy) {
|
|
19
|
+
this.policies.set(policy.name, policy);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Remove a policy by name
|
|
23
|
+
*/
|
|
24
|
+
removePolicy(name) {
|
|
25
|
+
this.policies.delete(name);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* clear all policies
|
|
29
|
+
*/
|
|
30
|
+
clear() {
|
|
31
|
+
this.policies.clear();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Load policies from declarative configurations (JSON)
|
|
35
|
+
* This is useful for loading policies saved from a UI
|
|
36
|
+
*/
|
|
37
|
+
loadFromConfigs(configs, replace = false) {
|
|
38
|
+
if (replace) {
|
|
39
|
+
this.policies.clear();
|
|
40
|
+
}
|
|
41
|
+
for (const config of configs) {
|
|
42
|
+
const policy = createDeclarativePolicy(config);
|
|
43
|
+
this.policies.set(policy.name, policy);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get all registered policies
|
|
48
|
+
*/
|
|
49
|
+
getPolicies() {
|
|
50
|
+
return Array.from(this.policies.values());
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Implementation of the SecurityPolicy check interface.
|
|
54
|
+
* Delegates to all registered policies.
|
|
55
|
+
*/
|
|
56
|
+
async check(toolName, args, getProvenance) {
|
|
57
|
+
let requiresApproval = null;
|
|
58
|
+
for (const policy of this.policies.values()) {
|
|
59
|
+
const result = await policy.check(toolName, args, getProvenance);
|
|
60
|
+
if (result.action === 'block') {
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
if (result.action === 'approve') {
|
|
64
|
+
if (!requiresApproval) {
|
|
65
|
+
requiresApproval = result;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (requiresApproval) {
|
|
70
|
+
return requiresApproval;
|
|
71
|
+
}
|
|
72
|
+
return { action: 'log' };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=dynamic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamic.js","sourceRoot":"","sources":["../../src/policies/dynamic.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAgC,MAAM,kBAAkB,CAAC;AAEzF;;;GAGG;AACH,MAAM,OAAO,qBAAqB;IACjC,IAAI,GAAG,yBAAyB,CAAC;IACjC,WAAW,GAAG,qDAAqD,CAAC;IAE5D,QAAQ,GAAgC,IAAI,GAAG,EAAE,CAAC;IAE1D,YAAY,kBAAoC,EAAE;QACjD,KAAK,MAAM,MAAM,IAAI,eAAe,EAAE,CAAC;YACtC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACxC,CAAC;IACF,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,MAAsB;QAC/B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,IAAY;QACxB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,KAAK;QACJ,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAED;;;OAGG;IACH,eAAe,CAAC,OAAkC,EAAE,OAAO,GAAG,KAAK;QAClE,IAAI,OAAO,EAAE,CAAC;YACb,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QACD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;YAC/C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACxC,CAAC;IACF,CAAC;IAED;;OAEG;IACH,WAAW;QACV,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,KAAK,CACV,QAAgB,EAChB,IAA6B,EAC7B,aAA4D;QAE5D,IAAI,gBAAgB,GAAwB,IAAI,CAAC;QAEjD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;YAEjE,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;gBAC/B,OAAO,MAAM,CAAC;YACf,CAAC;YAED,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACjC,IAAI,CAAC,gBAAgB,EAAE,CAAC;oBACvB,gBAAgB,GAAG,MAAM,CAAC;gBAC3B,CAAC;YACF,CAAC;QACF,CAAC;QAED,IAAI,gBAAgB,EAAE,CAAC;YACtB,OAAO,gBAAgB,CAAC;QACzB,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC1B,CAAC;CACD"}
|