@orygn/opa-mcp 0.4.0 → 0.5.0
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/CHANGELOG.md +339 -3
- package/README.md +71 -72
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +8 -3
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +57 -15
- package/dist/config.js.map +1 -1
- package/dist/lib/bundle-signatures.d.ts +23 -0
- package/dist/lib/bundle-signatures.d.ts.map +1 -0
- package/dist/lib/bundle-signatures.js +152 -0
- package/dist/lib/bundle-signatures.js.map +1 -0
- package/dist/lib/child-env.d.ts +9 -2
- package/dist/lib/child-env.d.ts.map +1 -1
- package/dist/lib/child-env.js +38 -6
- package/dist/lib/child-env.js.map +1 -1
- package/dist/lib/conftest-cli.d.ts +25 -10
- package/dist/lib/conftest-cli.d.ts.map +1 -1
- package/dist/lib/conftest-cli.js +152 -33
- package/dist/lib/conftest-cli.js.map +1 -1
- package/dist/lib/install-id.d.ts.map +1 -1
- package/dist/lib/install-id.js +18 -3
- package/dist/lib/install-id.js.map +1 -1
- package/dist/lib/json-stream.d.ts +26 -0
- package/dist/lib/json-stream.d.ts.map +1 -0
- package/dist/lib/json-stream.js +69 -0
- package/dist/lib/json-stream.js.map +1 -0
- package/dist/lib/opa-cli.d.ts +64 -16
- package/dist/lib/opa-cli.d.ts.map +1 -1
- package/dist/lib/opa-cli.js +98 -28
- package/dist/lib/opa-cli.js.map +1 -1
- package/dist/lib/opa-paths.d.ts +24 -0
- package/dist/lib/opa-paths.d.ts.map +1 -0
- package/dist/lib/opa-paths.js +97 -0
- package/dist/lib/opa-paths.js.map +1 -0
- package/dist/lib/regal-cli.d.ts +16 -1
- package/dist/lib/regal-cli.d.ts.map +1 -1
- package/dist/lib/regal-cli.js +40 -6
- package/dist/lib/regal-cli.js.map +1 -1
- package/dist/lib/rego-ast-walker.d.ts.map +1 -1
- package/dist/lib/rego-ast-walker.js +141 -17
- package/dist/lib/rego-ast-walker.js.map +1 -1
- package/dist/lib/rego-counterexample.d.ts +1 -1
- package/dist/lib/rego-counterexample.d.ts.map +1 -1
- package/dist/lib/rego-counterexample.js +23 -5
- package/dist/lib/rego-counterexample.js.map +1 -1
- package/dist/lib/rego-ir.d.ts +32 -2
- package/dist/lib/rego-ir.d.ts.map +1 -1
- package/dist/lib/rego-smt-encoder.d.ts +53 -5
- package/dist/lib/rego-smt-encoder.d.ts.map +1 -1
- package/dist/lib/rego-smt-encoder.js +192 -26
- package/dist/lib/rego-smt-encoder.js.map +1 -1
- package/dist/lib/rego-type-inferencer.d.ts +1 -1
- package/dist/lib/rego-type-inferencer.d.ts.map +1 -1
- package/dist/lib/rego-type-inferencer.js +3 -3
- package/dist/lib/rego-type-inferencer.js.map +1 -1
- package/dist/lib/rego-verify-engine.d.ts.map +1 -1
- package/dist/lib/rego-verify-engine.js +109 -77
- package/dist/lib/rego-verify-engine.js.map +1 -1
- package/dist/lib/rego-z3.d.ts +10 -0
- package/dist/lib/rego-z3.d.ts.map +1 -1
- package/dist/lib/rego-z3.js +38 -0
- package/dist/lib/rego-z3.js.map +1 -1
- package/dist/lib/security.d.ts +8 -0
- package/dist/lib/security.d.ts.map +1 -1
- package/dist/lib/security.js +130 -54
- package/dist/lib/security.js.map +1 -1
- package/dist/resources/patterns.d.ts +1 -1
- package/dist/resources/patterns.d.ts.map +1 -1
- package/dist/resources/patterns.js +40 -12
- package/dist/resources/patterns.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +10 -2
- package/dist/server.js.map +1 -1
- package/dist/tools/bundles/build.d.ts.map +1 -1
- package/dist/tools/bundles/build.js +12 -4
- package/dist/tools/bundles/build.js.map +1 -1
- package/dist/tools/bundles/sign.d.ts +9 -2
- package/dist/tools/bundles/sign.d.ts.map +1 -1
- package/dist/tools/bundles/sign.js +145 -19
- package/dist/tools/bundles/sign.js.map +1 -1
- package/dist/tools/bundles/verify.d.ts +1 -1
- package/dist/tools/bundles/verify.d.ts.map +1 -1
- package/dist/tools/bundles/verify.js +58 -19
- package/dist/tools/bundles/verify.js.map +1 -1
- package/dist/tools/conftest/pull.d.ts.map +1 -1
- package/dist/tools/conftest/pull.js +24 -10
- package/dist/tools/conftest/pull.js.map +1 -1
- package/dist/tools/conftest/push.d.ts.map +1 -1
- package/dist/tools/conftest/push.js +17 -7
- package/dist/tools/conftest/push.js.map +1 -1
- package/dist/tools/conftest/test.d.ts +10 -6
- package/dist/tools/conftest/test.d.ts.map +1 -1
- package/dist/tools/conftest/test.js +47 -24
- package/dist/tools/conftest/test.js.map +1 -1
- package/dist/tools/conftest/verify.d.ts +10 -6
- package/dist/tools/conftest/verify.d.ts.map +1 -1
- package/dist/tools/conftest/verify.js +30 -18
- package/dist/tools/conftest/verify.js.map +1 -1
- package/dist/tools/evaluation/bench.d.ts +16 -0
- package/dist/tools/evaluation/bench.d.ts.map +1 -1
- package/dist/tools/evaluation/bench.js +30 -5
- package/dist/tools/evaluation/bench.js.map +1 -1
- package/dist/tools/evaluation/exec.d.ts +16 -0
- package/dist/tools/evaluation/exec.d.ts.map +1 -1
- package/dist/tools/evaluation/exec.js +35 -2
- package/dist/tools/evaluation/exec.js.map +1 -1
- package/dist/tools/evaluation/test-multiroot.d.ts +4 -0
- package/dist/tools/evaluation/test-multiroot.d.ts.map +1 -1
- package/dist/tools/evaluation/test-multiroot.js +12 -2
- package/dist/tools/evaluation/test-multiroot.js.map +1 -1
- package/dist/tools/evaluation/test.d.ts +45 -0
- package/dist/tools/evaluation/test.d.ts.map +1 -1
- package/dist/tools/evaluation/test.js +146 -27
- package/dist/tools/evaluation/test.js.map +1 -1
- package/dist/tools/helpers/coverage-gaps.d.ts +11 -3
- package/dist/tools/helpers/coverage-gaps.d.ts.map +1 -1
- package/dist/tools/helpers/coverage-gaps.js +4 -3
- package/dist/tools/helpers/coverage-gaps.js.map +1 -1
- package/dist/tools/helpers/explain-undefined.d.ts +9 -3
- package/dist/tools/helpers/explain-undefined.d.ts.map +1 -1
- package/dist/tools/helpers/explain-undefined.js +83 -51
- package/dist/tools/helpers/explain-undefined.js.map +1 -1
- package/dist/tools/helpers/verify.d.ts.map +1 -1
- package/dist/tools/helpers/verify.js +5 -1
- package/dist/tools/helpers/verify.js.map +1 -1
- package/dist/tools/server-management/_shared.d.ts +15 -4
- package/dist/tools/server-management/_shared.d.ts.map +1 -1
- package/dist/tools/server-management/_shared.js +73 -12
- package/dist/tools/server-management/_shared.js.map +1 -1
- package/dist/tools/server-management/data.d.ts.map +1 -1
- package/dist/tools/server-management/data.js +88 -23
- package/dist/tools/server-management/data.js.map +1 -1
- package/dist/tools/server-management/decisions.d.ts.map +1 -1
- package/dist/tools/server-management/decisions.js +16 -3
- package/dist/tools/server-management/decisions.js.map +1 -1
- package/dist/tools/server-management/policies.d.ts.map +1 -1
- package/dist/tools/server-management/policies.js +44 -7
- package/dist/tools/server-management/policies.js.map +1 -1
- package/dist/tools/server-management/status.d.ts.map +1 -1
- package/dist/tools/server-management/status.js +80 -13
- package/dist/tools/server-management/status.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -1
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `opa_bundle_verify` -- verify the
|
|
3
|
-
*
|
|
2
|
+
* `opa_bundle_verify` -- verify the signature of a signed OPA bundle.
|
|
3
|
+
*
|
|
4
|
+
* OPA has no standalone verify command. The check runs as
|
|
5
|
+
* `opa build --verification-key` into a temp file that is discarded; see
|
|
6
|
+
* `OpaCli.bundleVerify`. A directory is verified by name from its parent, the
|
|
7
|
+
* same way `opa_bundle_sign` signs it. OPA reports the first failure it hits,
|
|
8
|
+
* and the reason is classified into `details.reason` so a caller can tell a
|
|
9
|
+
* wrong key from a tampered file.
|
|
4
10
|
*/
|
|
11
|
+
import { realpath, stat } from 'node:fs/promises';
|
|
12
|
+
import { basename, dirname } from 'node:path';
|
|
5
13
|
import { z } from 'zod';
|
|
6
|
-
import {
|
|
14
|
+
import { classifyVerificationFailure } from '../../lib/bundle-signatures.js';
|
|
7
15
|
import { err, ok } from '../../lib/errors.js';
|
|
16
|
+
import { OpaCli } from '../../lib/opa-cli.js';
|
|
8
17
|
import { mapSubprocessFailure, validatePaths, withToolEnvelope } from '../../lib/tool-helpers.js';
|
|
9
18
|
const OpaBundleVerifyInput = {
|
|
10
19
|
bundle: z
|
|
@@ -14,11 +23,11 @@ const OpaBundleVerifyInput = {
|
|
|
14
23
|
verificationKey: z
|
|
15
24
|
.string()
|
|
16
25
|
.min(1)
|
|
17
|
-
.describe('Path to the PEM file containing the RSA or ECDSA public key, or
|
|
26
|
+
.describe('Path to the PEM file containing the RSA or ECDSA public key, or for HMAC algorithms a file holding the secret. Must be inside an allowed root.'),
|
|
18
27
|
verificationKeyId: z
|
|
19
28
|
.string()
|
|
20
29
|
.optional()
|
|
21
|
-
.describe('
|
|
30
|
+
.describe('Name the key is registered under for OPA (`--verification-key-id`, default `default`). With a single key OPA verifies against it regardless of the signature keyid claim, so this rarely needs setting.'),
|
|
22
31
|
signingAlg: z
|
|
23
32
|
.string()
|
|
24
33
|
.optional()
|
|
@@ -26,13 +35,24 @@ const OpaBundleVerifyInput = {
|
|
|
26
35
|
scope: z
|
|
27
36
|
.string()
|
|
28
37
|
.optional()
|
|
29
|
-
.describe('Expected `scope`
|
|
38
|
+
.describe('Expected `scope` claim in the signature. Pass exactly the value the bundle was signed with, and nothing if it was signed without one; the failure reason is scope_mismatch otherwise.'),
|
|
39
|
+
v0Compatible: z
|
|
40
|
+
.boolean()
|
|
41
|
+
.optional()
|
|
42
|
+
.describe('Load the bundle as Rego v0 (`--v0-compatible`). A policy written before Rego v1 otherwise fails to load, after the signature and digests have already been checked.'),
|
|
30
43
|
};
|
|
31
44
|
export function registerOpaBundleVerify(server, config) {
|
|
32
45
|
const opa = new OpaCli(config);
|
|
33
46
|
server.registerTool('opa_bundle_verify', {
|
|
34
47
|
title: 'Verify OPA bundle signature',
|
|
35
|
-
description: 'Verify the
|
|
48
|
+
description: 'Verify the signature of a signed bundle directory or `.tar.gz` archive with the public key. ' +
|
|
49
|
+
'OPA has no standalone verify command, so this runs `opa build --verification-key` into a private temp file that is discarded. ' +
|
|
50
|
+
'A directory is verified by name from its parent, matching how `opa_bundle_sign` signs it. ' +
|
|
51
|
+
'OPA reads the key, checks the JWT in `.signatures.json`, compares the scope claim, then checks every file: Rego files by digest before parsing, data files and `.manifest` by parsed value, so an unparseable data file fails before its digest is compared. ' +
|
|
52
|
+
'Failures return `INVALID_BUNDLE` with `details.reason` set to one of signature_invalid, scope_mismatch, file_modified, file_added, file_missing, file_unparseable, unsigned, signatures_malformed, not_a_bundle, bundle_load_error, or unknown when the message is not recognised; the raw output is in `details`. ' +
|
|
53
|
+
'A key or algorithm OPA cannot use returns `INVALID_INPUT`. ' +
|
|
54
|
+
'Pass `scope` exactly as the bundle was signed with. With a single key OPA does not check `verificationKeyId` against the signature keyid claim. ' +
|
|
55
|
+
'`verified: true` is returned only when OPA loaded the bundle with its signature intact.',
|
|
36
56
|
inputSchema: OpaBundleVerifyInput,
|
|
37
57
|
annotations: {
|
|
38
58
|
readOnlyHint: true,
|
|
@@ -48,23 +68,42 @@ export function registerOpaBundleVerify(server, config) {
|
|
|
48
68
|
if (!validation.ok)
|
|
49
69
|
return validation.error;
|
|
50
70
|
const [resolvedBundle, resolvedKey] = validation.resolved;
|
|
51
|
-
|
|
52
|
-
|
|
71
|
+
// Same resolution as the sign tool: OPA does not descend a symlink or
|
|
72
|
+
// junction root, and a directory's signature names files under the
|
|
73
|
+
// directory name, so a directory is loaded by name from its parent.
|
|
74
|
+
const realBundle = await realpath(resolvedBundle);
|
|
75
|
+
const isDirectory = (await stat(realBundle)).isDirectory();
|
|
76
|
+
const verifyInput = {
|
|
77
|
+
bundle: isDirectory ? basename(realBundle) : realBundle,
|
|
53
78
|
verificationKey: resolvedKey,
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
79
|
+
};
|
|
80
|
+
if (isDirectory)
|
|
81
|
+
verifyInput.cwd = dirname(realBundle);
|
|
82
|
+
if (input.verificationKeyId !== undefined) {
|
|
83
|
+
verifyInput.verificationKeyId = input.verificationKeyId;
|
|
84
|
+
}
|
|
85
|
+
if (input.signingAlg !== undefined)
|
|
86
|
+
verifyInput.signingAlg = input.signingAlg;
|
|
87
|
+
if (input.scope !== undefined)
|
|
88
|
+
verifyInput.scope = input.scope;
|
|
89
|
+
if (input.v0Compatible)
|
|
90
|
+
verifyInput.v0Compatible = true;
|
|
91
|
+
const result = await opa.bundleVerify(verifyInput, signal);
|
|
58
92
|
const subprocessFailure = mapSubprocessFailure(result, 'opa');
|
|
59
93
|
if (subprocessFailure)
|
|
60
94
|
return subprocessFailure;
|
|
61
95
|
if (result.exitCode !== 0) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
96
|
+
// opa build prints the reason on stdout, not stderr.
|
|
97
|
+
const failure = classifyVerificationFailure(`${result.stdout}\n${result.stderr}`);
|
|
98
|
+
const details = {
|
|
99
|
+
reason: failure.reason,
|
|
100
|
+
stdout: result.stdout.trim(),
|
|
101
|
+
stderr: result.stderr.trim(),
|
|
102
|
+
};
|
|
103
|
+
if (failure.reason === 'key_invalid') {
|
|
104
|
+
return err('INVALID_INPUT', `The verification key or algorithm could not be used: ${failure.summary}.`, { hint: failure.hint, details });
|
|
105
|
+
}
|
|
106
|
+
return err('INVALID_BUNDLE', `Bundle signature verification failed: ${failure.summary}.`, { hint: failure.hint, details });
|
|
68
107
|
}
|
|
69
108
|
return ok({ bundle: input.bundle, verified: true });
|
|
70
109
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../../src/tools/bundles/verify.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../../src/tools/bundles/verify.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/pull.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/pull.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AA4B9C,MAAM,WAAW,kBAAkB;IACjC,+BAA+B;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;CACnB;AAKD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAuE5E"}
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
* 0 -- pull succeeded
|
|
18
18
|
* non-0 -- network / auth error
|
|
19
19
|
*/
|
|
20
|
+
import { mkdir } from 'node:fs/promises';
|
|
21
|
+
import { dirname, resolve } from 'node:path';
|
|
20
22
|
import { z } from 'zod';
|
|
21
23
|
import { ConftestCli } from '../../lib/conftest-cli.js';
|
|
22
24
|
import { err, ok } from '../../lib/errors.js';
|
|
@@ -35,8 +37,12 @@ const ConftestPullInput = {
|
|
|
35
37
|
.optional()
|
|
36
38
|
.describe('Local directory where the pulled policies will be written. ' +
|
|
37
39
|
'Must be inside an allowed root (OPA_MCP_ALLOWED_PATHS). ' +
|
|
38
|
-
|
|
40
|
+
'Omitted, it falls back to `policy` in the working directory of the server process, the conftest convention, which must itself sit inside an allowed root. ' +
|
|
41
|
+
'The directory is emptied before the pull, so do not point it at one holding anything ' +
|
|
42
|
+
'you want to keep.'),
|
|
39
43
|
};
|
|
44
|
+
/** Where conftest looks when `--policy` is not given, as an absolute path. */
|
|
45
|
+
const DEFAULT_POLICY_DIR = resolve('policy');
|
|
40
46
|
export function registerConftestPull(server, config) {
|
|
41
47
|
const conftest = new ConftestCli(config);
|
|
42
48
|
server.registerTool('conftest_pull', {
|
|
@@ -59,24 +65,32 @@ export function registerConftestPull(server, config) {
|
|
|
59
65
|
}, async (input, { signal }) => {
|
|
60
66
|
return withToolEnvelope(config, async () => {
|
|
61
67
|
// ── Path validation ──────────────────────────────────────────────
|
|
62
|
-
// The
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
// The directory does not have to exist yet; conftest creates it. An
|
|
69
|
+
// omitted path means conftest's own default, which it resolves against
|
|
70
|
+
// the working directory. This tool writes files, so that default is
|
|
71
|
+
// checked against the allow-list too rather than escaping it by being
|
|
72
|
+
// implicit.
|
|
73
|
+
const v = validatePaths([input.policy ?? DEFAULT_POLICY_DIR], config);
|
|
74
|
+
if (!v.ok) {
|
|
75
|
+
if (input.policy !== undefined)
|
|
68
76
|
return v.error;
|
|
69
|
-
|
|
77
|
+
return err('PATH_NOT_ALLOWED', 'The conftest default policy directory is outside the allowed roots.', {
|
|
78
|
+
hint: 'Pass `policy` with a directory inside OPA_MCP_ALLOWED_PATHS.',
|
|
79
|
+
details: { defaultPolicyDir: DEFAULT_POLICY_DIR },
|
|
80
|
+
});
|
|
70
81
|
}
|
|
82
|
+
const policyDir = v.resolved[0];
|
|
83
|
+
// conftest runs from the parent, so the parent has to exist.
|
|
84
|
+
await mkdir(dirname(policyDir), { recursive: true });
|
|
71
85
|
// ── Run conftest pull ────────────────────────────────────────────
|
|
72
|
-
const result = await conftest.pull({ url: input.url, policy:
|
|
86
|
+
const result = await conftest.pull({ url: input.url, policy: policyDir }, signal);
|
|
73
87
|
const subprocessFailure = mapSubprocessFailure(result, 'conftest');
|
|
74
88
|
if (subprocessFailure)
|
|
75
89
|
return subprocessFailure;
|
|
76
90
|
if (result.exitCode === 0) {
|
|
77
91
|
return ok({
|
|
78
92
|
url: input.url,
|
|
79
|
-
policyDir
|
|
93
|
+
policyDir,
|
|
80
94
|
});
|
|
81
95
|
}
|
|
82
96
|
const detail = result.stderr.trim() || result.stdout.trim();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.js","sourceRoot":"","sources":["../../../src/tools/conftest/pull.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElG,MAAM,iBAAiB,GAAG;IACxB,GAAG,EAAE,CAAC;SACH,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CACP,yCAAyC;QACvC,4CAA4C;QAC5C,qDAAqD;QACrD,uDAAuD;QACvD,gEAAgE,CACnE;IACH,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,6DAA6D;QAC3D,0DAA0D;QAC1D,
|
|
1
|
+
{"version":3,"file":"pull.js","sourceRoot":"","sources":["../../../src/tools/conftest/pull.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/push.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/push.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAyB9C,MAAM,WAAW,kBAAkB;IACjC,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;CACnB;AAKD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAkE5E"}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* non-0 -- push error (auth failure, network error, etc.)
|
|
15
15
|
*/
|
|
16
16
|
import { z } from 'zod';
|
|
17
|
+
import { resolve } from 'node:path';
|
|
17
18
|
import { ConftestCli } from '../../lib/conftest-cli.js';
|
|
18
19
|
import { err, ok } from '../../lib/errors.js';
|
|
19
20
|
import { mapSubprocessFailure, validatePaths, withToolEnvelope } from '../../lib/tool-helpers.js';
|
|
@@ -30,8 +31,10 @@ const ConftestPushInput = {
|
|
|
30
31
|
.optional()
|
|
31
32
|
.describe('Path to the local directory containing Rego policies to push. ' +
|
|
32
33
|
'Must be inside an allowed root (OPA_MCP_ALLOWED_PATHS) and must exist. ' +
|
|
33
|
-
|
|
34
|
+
'Omitted, it falls back to `policy` in the working directory of the server process, the conftest convention, which must itself sit inside an allowed root.'),
|
|
34
35
|
};
|
|
36
|
+
/** Where conftest looks when `--policy` is not given, as an absolute path. */
|
|
37
|
+
const DEFAULT_POLICY_DIR = resolve('policy');
|
|
35
38
|
export function registerConftestPush(server, config) {
|
|
36
39
|
const conftest = new ConftestCli(config);
|
|
37
40
|
server.registerTool('conftest_push', {
|
|
@@ -51,21 +54,28 @@ export function registerConftestPush(server, config) {
|
|
|
51
54
|
}, async (input, { signal }) => {
|
|
52
55
|
return withToolEnvelope(config, async () => {
|
|
53
56
|
// ── Path validation ──────────────────────────────────────────────
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
// An omitted path means the conftest default, resolved against the
|
|
58
|
+
// working directory. This publishes whatever it finds there, so the
|
|
59
|
+
// default is checked against the allow-list like an explicit one.
|
|
60
|
+
const v = validatePaths([input.policy ?? DEFAULT_POLICY_DIR], config, { mustExist: true });
|
|
61
|
+
if (!v.ok) {
|
|
62
|
+
if (input.policy !== undefined)
|
|
57
63
|
return v.error;
|
|
58
|
-
|
|
64
|
+
return err('PATH_NOT_ALLOWED', 'The conftest default policy directory is outside the allowed roots.', {
|
|
65
|
+
hint: 'Pass `policy` with a directory inside OPA_MCP_ALLOWED_PATHS.',
|
|
66
|
+
details: { defaultPolicyDir: DEFAULT_POLICY_DIR },
|
|
67
|
+
});
|
|
59
68
|
}
|
|
69
|
+
const policyDir = v.resolved[0];
|
|
60
70
|
// ── Run conftest push ────────────────────────────────────────────
|
|
61
|
-
const result = await conftest.push({ repository: input.repository, policy:
|
|
71
|
+
const result = await conftest.push({ repository: input.repository, policy: policyDir }, signal);
|
|
62
72
|
const subprocessFailure = mapSubprocessFailure(result, 'conftest');
|
|
63
73
|
if (subprocessFailure)
|
|
64
74
|
return subprocessFailure;
|
|
65
75
|
if (result.exitCode === 0) {
|
|
66
76
|
return ok({
|
|
67
77
|
repository: input.repository,
|
|
68
|
-
policyDir
|
|
78
|
+
policyDir,
|
|
69
79
|
});
|
|
70
80
|
}
|
|
71
81
|
const detail = result.stderr.trim() || result.stdout.trim();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../../src/tools/conftest/push.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../../src/tools/conftest/push.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,19 +2,23 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import type { Config } from '../../config.js';
|
|
3
3
|
import { type ConftestFileResult } from '../../lib/conftest-cli.js';
|
|
4
4
|
export interface ConftestTestOutput {
|
|
5
|
-
/** `true` when no failures
|
|
5
|
+
/** `true` when conftest exited 0: no failures, and no warnings if `failOnWarn` was set. */
|
|
6
6
|
passed: boolean;
|
|
7
|
-
/**
|
|
7
|
+
/** One entry per (file, namespace) pair conftest evaluated, arrays always present. */
|
|
8
8
|
results: ConftestFileResult[];
|
|
9
9
|
summary: {
|
|
10
|
-
/**
|
|
10
|
+
/** Distinct files with no failure in any namespace. */
|
|
11
11
|
passed: number;
|
|
12
|
-
/**
|
|
12
|
+
/** Distinct files with at least one failure in any namespace. */
|
|
13
13
|
failed: number;
|
|
14
|
-
/**
|
|
14
|
+
/** Warning messages across all entries. */
|
|
15
15
|
warnings: number;
|
|
16
|
-
/**
|
|
16
|
+
/** Skipped-rule messages across all entries. */
|
|
17
17
|
skipped: number;
|
|
18
|
+
/** Rule evaluations that passed across all entries (conftest's `successes`). */
|
|
19
|
+
successes: number;
|
|
20
|
+
/** Failure messages across all entries. */
|
|
21
|
+
failures: number;
|
|
18
22
|
};
|
|
19
23
|
}
|
|
20
24
|
export declare function registerConftestTest(server: McpServer, config: Config): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/test.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/test.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAKL,KAAK,kBAAkB,EACxB,MAAM,2BAA2B,CAAC;AAuFnC,MAAM,WAAW,kBAAkB;IACjC,2FAA2F;IAC3F,MAAM,EAAE,OAAO,CAAC;IAChB,sFAAsF;IACtF,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,OAAO,EAAE;QACP,uDAAuD;QACvD,MAAM,EAAE,MAAM,CAAC;QACf,iEAAiE;QACjE,MAAM,EAAE,MAAM,CAAC;QACf,2CAA2C;QAC3C,QAAQ,EAAE,MAAM,CAAC;QACjB,gDAAgD;QAChD,OAAO,EAAE,MAAM,CAAC;QAChB,gFAAgF;QAChF,SAAS,EAAE,MAAM,CAAC;QAClB,2CAA2C;QAC3C,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CA+H5E"}
|
|
@@ -15,9 +15,10 @@
|
|
|
15
15
|
* 2+ -- command error (bad args, policy not found, etc.)
|
|
16
16
|
*/
|
|
17
17
|
import { z } from 'zod';
|
|
18
|
-
import { ConftestCli } from '../../lib/conftest-cli.js';
|
|
18
|
+
import { CONFTEST_PARSERS, ConftestCli, isConftestParser, parseConftestResults, } from '../../lib/conftest-cli.js';
|
|
19
19
|
import { err, ok } from '../../lib/errors.js';
|
|
20
|
-
import { mapSubprocessFailure,
|
|
20
|
+
import { mapSubprocessFailure, validatePaths, withToolEnvelope } from '../../lib/tool-helpers.js';
|
|
21
|
+
const PARSER_LIST = CONFTEST_PARSERS.join(', ');
|
|
21
22
|
const ConftestTestInput = {
|
|
22
23
|
files: z
|
|
23
24
|
.array(z.string())
|
|
@@ -31,19 +32,17 @@ const ConftestTestInput = {
|
|
|
31
32
|
.describe('Inline configuration content to evaluate (e.g. a Kubernetes manifest as a YAML string). ' +
|
|
32
33
|
'Mutually exclusive with `files`. Defaults to YAML format; set `inlineConfigParser` to override.'),
|
|
33
34
|
inlineConfigParser: z
|
|
34
|
-
.
|
|
35
|
+
.enum(CONFTEST_PARSERS)
|
|
35
36
|
.optional()
|
|
36
|
-
.describe(
|
|
37
|
-
'ini, xml, dotenv, cue, jsonnet, properties, edn, hocon, dockerfile. ' +
|
|
37
|
+
.describe(`Parser to use for \`inlineConfig\`. One of: ${PARSER_LIST}. Defaults to yaml. ` +
|
|
38
38
|
"Ignored when `files` is used (conftest infers the parser from each file's extension, " +
|
|
39
39
|
'unless `parser` is set).'),
|
|
40
40
|
parser: z
|
|
41
|
-
.
|
|
41
|
+
.enum(CONFTEST_PARSERS)
|
|
42
42
|
.optional()
|
|
43
43
|
.describe("Force a specific parser for all input `files` via conftest's global `--parser` flag, " +
|
|
44
44
|
'overriding extension-based detection. Useful for files whose extension does not match ' +
|
|
45
|
-
|
|
46
|
-
'hcl1, hcl2, ini, xml, dotenv, cue, jsonnet, properties, edn, hocon, dockerfile. ' +
|
|
45
|
+
`their format (e.g. parse a \`.tfstate\` file as \`json\`). One of: ${PARSER_LIST}. ` +
|
|
47
46
|
'For `inlineConfig`, prefer `inlineConfigParser`.'),
|
|
48
47
|
policy: z
|
|
49
48
|
.string()
|
|
@@ -93,13 +92,14 @@ export function registerConftestTest(server, config) {
|
|
|
93
92
|
'CONFTEST_NOT_FOUND otherwise. ' +
|
|
94
93
|
'Provide config via `files` (disk paths) or `inlineConfig` (inline string). ' +
|
|
95
94
|
'Provide policy via `policy` (disk path) or `inlinePolicy` (inline Rego source). ' +
|
|
96
|
-
"Omit `policy` and `inlinePolicy` to use conftest's default `./policy` directory."
|
|
95
|
+
"Omit `policy` and `inlinePolicy` to use conftest's default `./policy` directory. " +
|
|
96
|
+
'Policies are executed by conftest and can call OPA built-ins such as http.send.',
|
|
97
97
|
inputSchema: ConftestTestInput,
|
|
98
98
|
annotations: {
|
|
99
99
|
readOnlyHint: true,
|
|
100
100
|
destructiveHint: false,
|
|
101
101
|
idempotentHint: true,
|
|
102
|
-
openWorldHint:
|
|
102
|
+
openWorldHint: true,
|
|
103
103
|
},
|
|
104
104
|
}, async (input, { signal }) => {
|
|
105
105
|
return withToolEnvelope(config, async () => {
|
|
@@ -113,6 +113,20 @@ export function registerConftestTest(server, config) {
|
|
|
113
113
|
if (input.policy !== undefined && input.inlinePolicy !== undefined) {
|
|
114
114
|
return err('INVALID_INPUT', '`policy` and `inlinePolicy` are mutually exclusive.');
|
|
115
115
|
}
|
|
116
|
+
// The schema restricts parser names to the closed set, and the
|
|
117
|
+
// check is repeated here because the name becomes part of a temp
|
|
118
|
+
// file path: this handler must never see free text there, whatever
|
|
119
|
+
// path it was reached by.
|
|
120
|
+
for (const [field, value] of [
|
|
121
|
+
['inlineConfigParser', input.inlineConfigParser],
|
|
122
|
+
['parser', input.parser],
|
|
123
|
+
]) {
|
|
124
|
+
if (value !== undefined && !isConftestParser(value)) {
|
|
125
|
+
return err('INVALID_INPUT', `\`${field}\` must be one of: ${PARSER_LIST}.`, {
|
|
126
|
+
details: { [field]: value },
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
116
130
|
// ── Path validation ──────────────────────────────────────────────
|
|
117
131
|
if (input.files?.length) {
|
|
118
132
|
const v = validatePaths(input.files, config, { mustExist: true });
|
|
@@ -154,17 +168,16 @@ export function registerConftestTest(server, config) {
|
|
|
154
168
|
// Exit 0 = all pass, exit 1 = failures present.
|
|
155
169
|
// Both produce valid JSON on stdout.
|
|
156
170
|
if (result.exitCode === 0 || result.exitCode === 1) {
|
|
157
|
-
const
|
|
158
|
-
if (
|
|
171
|
+
const results = parseConftestResults(result.stdout);
|
|
172
|
+
if (results === null) {
|
|
159
173
|
return err('UNKNOWN_ERROR', 'conftest test produced no parseable JSON output.', {
|
|
160
174
|
details: { stderr: result.stderr.trim(), exitCode: result.exitCode },
|
|
161
175
|
});
|
|
162
176
|
}
|
|
163
|
-
const summary = buildSummary(parsed);
|
|
164
177
|
return ok({
|
|
165
178
|
passed: result.exitCode === 0,
|
|
166
|
-
results
|
|
167
|
-
summary,
|
|
179
|
+
results,
|
|
180
|
+
summary: buildSummary(results),
|
|
168
181
|
});
|
|
169
182
|
}
|
|
170
183
|
// ── Exit code 2+: command-level error ────────────────────────────
|
|
@@ -177,20 +190,30 @@ export function registerConftestTest(server, config) {
|
|
|
177
190
|
}
|
|
178
191
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
179
192
|
function buildSummary(results) {
|
|
180
|
-
|
|
181
|
-
|
|
193
|
+
// conftest emits one entry per (file, namespace); with --all-namespaces a
|
|
194
|
+
// file appears once per namespace, so files are counted by name.
|
|
195
|
+
const failedFiles = new Set();
|
|
196
|
+
const allFiles = new Set();
|
|
182
197
|
let warnings = 0;
|
|
183
198
|
let skipped = 0;
|
|
199
|
+
let successes = 0;
|
|
200
|
+
let failures = 0;
|
|
184
201
|
for (const r of results) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
else {
|
|
189
|
-
passed++;
|
|
190
|
-
}
|
|
202
|
+
allFiles.add(r.filename);
|
|
203
|
+
if (r.failures.length > 0)
|
|
204
|
+
failedFiles.add(r.filename);
|
|
191
205
|
warnings += r.warnings.length;
|
|
192
206
|
skipped += r.skipped.length;
|
|
207
|
+
successes += r.successes;
|
|
208
|
+
failures += r.failures.length;
|
|
193
209
|
}
|
|
194
|
-
return {
|
|
210
|
+
return {
|
|
211
|
+
passed: allFiles.size - failedFiles.size,
|
|
212
|
+
failed: failedFiles.size,
|
|
213
|
+
warnings,
|
|
214
|
+
skipped,
|
|
215
|
+
successes,
|
|
216
|
+
failures,
|
|
217
|
+
};
|
|
195
218
|
}
|
|
196
219
|
//# sourceMappingURL=test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../../src/tools/conftest/test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../../src/tools/conftest/test.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,18 +2,22 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import type { Config } from '../../config.js';
|
|
3
3
|
import { type ConftestFileResult } from '../../lib/conftest-cli.js';
|
|
4
4
|
export interface ConftestVerifyOutput {
|
|
5
|
-
/** `true` when
|
|
5
|
+
/** `true` when every `test_*` rule passed. */
|
|
6
6
|
passed: boolean;
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* One entry per test outcome as conftest reports them: a test file
|
|
9
|
+
* produces one entry per passing rule (`successes: 1`) and one per
|
|
10
|
+
* failing rule (`failures: [{msg}]`), with `namespace` empty.
|
|
11
|
+
*/
|
|
8
12
|
results: ConftestFileResult[];
|
|
9
13
|
summary: {
|
|
10
|
-
/**
|
|
14
|
+
/** Distinct test files with no failing rule. */
|
|
11
15
|
passed: number;
|
|
12
|
-
/**
|
|
16
|
+
/** Distinct test files with at least one failing rule. */
|
|
13
17
|
failed: number;
|
|
14
|
-
/**
|
|
18
|
+
/** Test rules that passed, across all files. */
|
|
15
19
|
totalPassed: number;
|
|
16
|
-
/**
|
|
20
|
+
/** Test rules that failed, across all files. */
|
|
17
21
|
totalFailed: number;
|
|
18
22
|
};
|
|
19
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/verify.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/verify.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,2BAA2B,CAAC;AAyBnC,MAAM,WAAW,oBAAoB;IACnC,8CAA8C;IAC9C,MAAM,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,OAAO,EAAE;QACP,gDAAgD;QAChD,MAAM,EAAE,MAAM,CAAC;QACf,0DAA0D;QAC1D,MAAM,EAAE,MAAM,CAAC;QACf,gDAAgD;QAChD,WAAW,EAAE,MAAM,CAAC;QACpB,gDAAgD;QAChD,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAqF9E"}
|