@mitre/hdf-generators 3.0.1 → 3.1.0-rc.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/LICENSE.md +55 -0
- package/dist/index.d.ts +83 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +173 -4
- package/dist/index.js.map +1 -1
- package/package.json +18 -18
- package/dist/control-stub.d.ts +0 -16
- package/dist/control-stub.d.ts.map +0 -1
- package/dist/control-stub.js +0 -81
- package/dist/control-stub.js.map +0 -1
- package/dist/inspec-yml.d.ts +0 -10
- package/dist/inspec-yml.d.ts.map +0 -1
- package/dist/inspec-yml.js +0 -113
- package/dist/inspec-yml.js.map +0 -1
- package/dist/profile-generator.d.ts +0 -11
- package/dist/profile-generator.d.ts.map +0 -1
- package/dist/profile-generator.js +0 -31
- package/dist/profile-generator.js.map +0 -1
- package/dist/ruby-escape.d.ts +0 -13
- package/dist/ruby-escape.d.ts.map +0 -1
- package/dist/ruby-escape.js +0 -26
- package/dist/ruby-escape.js.map +0 -1
- package/dist/types.d.ts +0 -30
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
package/LICENSE.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# License
|
|
2
|
+
|
|
3
|
+
Copyright © 2025 The MITRE Corporation.
|
|
4
|
+
|
|
5
|
+
Approved for Public Release; Distribution Unlimited. Case Number 18-3678.
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
8
|
+
not use this file except in compliance with the License. You may obtain a
|
|
9
|
+
copy of the License at
|
|
10
|
+
|
|
11
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
|
|
13
|
+
Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
15
|
+
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
16
|
+
License for the specific language governing permissions and limitations
|
|
17
|
+
under the License.
|
|
18
|
+
|
|
19
|
+
## Redistribution Terms
|
|
20
|
+
|
|
21
|
+
Redistribution and use in source and binary forms, with or without
|
|
22
|
+
modification, are permitted provided that the following conditions are
|
|
23
|
+
met:
|
|
24
|
+
|
|
25
|
+
- Redistributions of source code must retain the above copyright/digital
|
|
26
|
+
rights legend, this list of conditions and the following Notice.
|
|
27
|
+
- Redistributions in binary form must reproduce the above
|
|
28
|
+
copyright/digital rights legend, this list of conditions and the
|
|
29
|
+
following Notice in the documentation and/or other materials provided
|
|
30
|
+
with the distribution.
|
|
31
|
+
- Neither the name of The MITRE Corporation nor the names of its contributors
|
|
32
|
+
may be used to endorse or promote products derived from this software
|
|
33
|
+
without specific prior written permission.
|
|
34
|
+
|
|
35
|
+
## Notice
|
|
36
|
+
|
|
37
|
+
The MITRE Corporation grants permission to reproduce, distribute, modify, and
|
|
38
|
+
otherwise use this software to the extent permitted by the licensed terms
|
|
39
|
+
provided in the LICENSE file included with this project.
|
|
40
|
+
|
|
41
|
+
This software was produced by The MITRE Corporation for the U.S. Government
|
|
42
|
+
under contract. As such the U.S. Government has certain use and data
|
|
43
|
+
rights in this software. No use other than those granted to the U.S.
|
|
44
|
+
Government, or to those acting on behalf of the U.S. Government, under
|
|
45
|
+
these contract arrangements is authorized without the express written
|
|
46
|
+
permission of The MITRE Corporation.
|
|
47
|
+
|
|
48
|
+
Some files in this codebase were generated by generative AI, under the
|
|
49
|
+
direction and review of The MITRE Corporation employees, for the purpose of
|
|
50
|
+
development efficiency. All AI-generated code functionality was validated
|
|
51
|
+
by standard quality and assurance testing.
|
|
52
|
+
|
|
53
|
+
For further information, please contact The MITRE Corporation,
|
|
54
|
+
Contracts Management Office, 7515 Colshire Drive, McLean, VA 22102-7539,
|
|
55
|
+
(703) 983-6000.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,84 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { BaselineRequirement, HdfBaseline } from "@mitre/hdf-schema";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Options for controlling InSpec profile generation.
|
|
6
|
+
*/
|
|
7
|
+
interface GeneratorOptions {
|
|
8
|
+
/** Put all controls in a single controls.rb file instead of one file per control. */
|
|
9
|
+
singleFile?: boolean;
|
|
10
|
+
/** Override baseline metadata in the generated inspec.yml. */
|
|
11
|
+
metadata?: ProfileMetadata;
|
|
12
|
+
/** InSpec version constraint for inspec.yml. Default: '~>6.0'. */
|
|
13
|
+
inspecVersion?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Metadata overrides for the generated inspec.yml.
|
|
17
|
+
*/
|
|
18
|
+
interface ProfileMetadata {
|
|
19
|
+
maintainer?: string;
|
|
20
|
+
copyright?: string;
|
|
21
|
+
license?: string;
|
|
22
|
+
version?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* An in-memory InSpec profile. No file I/O — the CLI is responsible for writing.
|
|
26
|
+
*/
|
|
27
|
+
interface InSpecProfile {
|
|
28
|
+
/** The inspec.yml content as a YAML string. */
|
|
29
|
+
inspecYml: string;
|
|
30
|
+
/** Map of filename (e.g. 'controls/SV-238196.rb') to Ruby source code. */
|
|
31
|
+
controls: Map<string, string>;
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/ruby-escape.d.ts
|
|
35
|
+
/**
|
|
36
|
+
* Escape a string for use as a Ruby string literal.
|
|
37
|
+
*
|
|
38
|
+
* Strategy:
|
|
39
|
+
* - If the string contains both single and double quotes → %q() wrapper
|
|
40
|
+
* - If the string contains only single quotes → double-quoted with escaping
|
|
41
|
+
* - Otherwise → single-quoted with escaping
|
|
42
|
+
*
|
|
43
|
+
* Ported from ts-inspec-objects escapeQuotes(), cross-referenced with
|
|
44
|
+
* inspec-parser's RubyRebuilder.
|
|
45
|
+
*/
|
|
46
|
+
declare function escapeQuotes(s: string): string;
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/control-stub.d.ts
|
|
49
|
+
/**
|
|
50
|
+
* Generate a Ruby InSpec control stub from an HDF BaselineRequirement.
|
|
51
|
+
*
|
|
52
|
+
* Output follows the InSpec DSL ordering convention:
|
|
53
|
+
* control 'ID' do
|
|
54
|
+
* title ...
|
|
55
|
+
* desc ...
|
|
56
|
+
* desc 'check', ...
|
|
57
|
+
* impact ...
|
|
58
|
+
* tag key: value
|
|
59
|
+
* <code or stub comment>
|
|
60
|
+
* end
|
|
61
|
+
*/
|
|
62
|
+
declare function generateControlStub(req: BaselineRequirement): string;
|
|
63
|
+
//#endregion
|
|
64
|
+
//#region src/inspec-yml.d.ts
|
|
65
|
+
/**
|
|
66
|
+
* Generate an inspec.yml YAML string from an HDF Baseline and options.
|
|
67
|
+
*
|
|
68
|
+
* Uses string interpolation — no YAML library needed since the structure
|
|
69
|
+
* is fixed and shallow.
|
|
70
|
+
*/
|
|
71
|
+
declare function generateInSpecYml(baseline: HdfBaseline, options?: GeneratorOptions): string;
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/profile-generator.d.ts
|
|
74
|
+
/**
|
|
75
|
+
* Generate an in-memory InSpec profile from an HDF Baseline.
|
|
76
|
+
*
|
|
77
|
+
* Returns an InSpecProfile with inspec.yml content and a Map of
|
|
78
|
+
* control filenames to Ruby source code. No file I/O — the CLI
|
|
79
|
+
* is responsible for writing files to disk.
|
|
80
|
+
*/
|
|
81
|
+
declare function generateInSpecProfile(baseline: HdfBaseline, options?: GeneratorOptions): InSpecProfile;
|
|
82
|
+
//#endregion
|
|
83
|
+
export { type GeneratorOptions, type InSpecProfile, type ProfileMetadata, escapeQuotes, generateControlStub, generateInSpecProfile, generateInSpecYml };
|
|
6
84
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/ruby-escape.ts","../src/control-stub.ts","../src/inspec-yml.ts","../src/profile-generator.ts"],"mappings":";;;;;;UAGiB,gBAAA;EAAgB;EAE/B,UAAA;EAE0B;EAA1B,QAAA,GAAW,eAAA;EAAX;EAEA,aAAA;AAAA;;;AAMF;UAAiB,eAAA;EACf,UAAA;EACA,SAAA;EACA,OAAA;EACA,OAAA;AAAA;;;;UAMe,aAAA;EAAa;EAE5B,SAAA;EAEa;EAAb,QAAA,EAAU,GAAA;AAAA;;;;;;AA1BZ;;;;;;;;iBCQgB,YAAA,CAAa,CAAA;;;;;ADR7B;;;;;;;;;;AAYA;iBECgB,mBAAA,CAAoB,GAAA,EAAK,mBAAA;;;;AFbzC;;;;;iBGMgB,iBAAA,CACd,QAAA,EAAU,WAAA,EACV,OAAA,GAAU,gBAAA;;;;AHRZ;;;;;;iBISgB,qBAAA,CACd,QAAA,EAAU,WAAA,EACV,OAAA,GAAU,gBAAA,GACT,aAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,174 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
//#region src/ruby-escape.ts
|
|
2
|
+
/**
|
|
3
|
+
* Escape a string for use as a Ruby string literal.
|
|
4
|
+
*
|
|
5
|
+
* Strategy:
|
|
6
|
+
* - If the string contains both single and double quotes → %q() wrapper
|
|
7
|
+
* - If the string contains only single quotes → double-quoted with escaping
|
|
8
|
+
* - Otherwise → single-quoted with escaping
|
|
9
|
+
*
|
|
10
|
+
* Ported from ts-inspec-objects escapeQuotes(), cross-referenced with
|
|
11
|
+
* inspec-parser's RubyRebuilder.
|
|
12
|
+
*/
|
|
13
|
+
function escapeQuotes(s) {
|
|
14
|
+
const hasSingle = s.includes("'");
|
|
15
|
+
const hasDouble = s.includes("\"");
|
|
16
|
+
if (hasSingle && hasDouble) return `%q(${s.replace(/\\\)/g, "\\\\)")})`;
|
|
17
|
+
if (hasSingle) return `"${s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
|
|
18
|
+
return `'${s.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/control-stub.ts
|
|
22
|
+
/**
|
|
23
|
+
* Generate a Ruby InSpec control stub from an HDF BaselineRequirement.
|
|
24
|
+
*
|
|
25
|
+
* Output follows the InSpec DSL ordering convention:
|
|
26
|
+
* control 'ID' do
|
|
27
|
+
* title ...
|
|
28
|
+
* desc ...
|
|
29
|
+
* desc 'check', ...
|
|
30
|
+
* impact ...
|
|
31
|
+
* tag key: value
|
|
32
|
+
* <code or stub comment>
|
|
33
|
+
* end
|
|
34
|
+
*/
|
|
35
|
+
function generateControlStub(req) {
|
|
36
|
+
const lines = [];
|
|
37
|
+
lines.push(`control '${req.id}' do`);
|
|
38
|
+
if (req.title) lines.push(` title ${escapeQuotes(req.title)}`);
|
|
39
|
+
const defaultDesc = req.descriptions.find((d) => d.label === "default");
|
|
40
|
+
if (defaultDesc) lines.push(` desc ${escapeQuotes(defaultDesc.data)}`);
|
|
41
|
+
const seenDefault = /* @__PURE__ */ new Set();
|
|
42
|
+
for (const d of req.descriptions) {
|
|
43
|
+
if (d.label === "default") {
|
|
44
|
+
if (seenDefault.has("default")) continue;
|
|
45
|
+
seenDefault.add("default");
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
lines.push(` desc '${d.label}', ${escapeQuotes(d.data)}`);
|
|
49
|
+
}
|
|
50
|
+
if (req.impact !== void 0) {
|
|
51
|
+
const impactStr = Number.isInteger(req.impact) ? req.impact.toFixed(1) : String(req.impact);
|
|
52
|
+
lines.push(` impact ${impactStr}`);
|
|
53
|
+
}
|
|
54
|
+
for (const [key, value] of Object.entries(req.tags)) lines.push(` ${formatTag(key, value)}`);
|
|
55
|
+
if (req.code) {
|
|
56
|
+
lines.push("");
|
|
57
|
+
lines.push(req.code);
|
|
58
|
+
} else {
|
|
59
|
+
lines.push("");
|
|
60
|
+
lines.push(" # TODO: Add InSpec test code here");
|
|
61
|
+
}
|
|
62
|
+
lines.push("end");
|
|
63
|
+
lines.push("");
|
|
64
|
+
return lines.join("\n");
|
|
65
|
+
}
|
|
66
|
+
/** Format a single tag key-value pair as Ruby DSL. */
|
|
67
|
+
function formatTag(key, value) {
|
|
68
|
+
if (value === null || value === void 0) return `tag ${key}: nil`;
|
|
69
|
+
if (Array.isArray(value)) return `tag ${key}: [${value.map((v) => `'${String(v)}'`).join(", ")}]`;
|
|
70
|
+
if (typeof value === "boolean") return `tag ${key}: ${value}`;
|
|
71
|
+
if (typeof value === "string") return `tag ${key}: ${escapeQuotes(value)}`;
|
|
72
|
+
return `tag ${key}: ${JSON.stringify(value)}`;
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/inspec-yml.ts
|
|
76
|
+
/**
|
|
77
|
+
* Generate an inspec.yml YAML string from an HDF Baseline and options.
|
|
78
|
+
*
|
|
79
|
+
* Uses string interpolation — no YAML library needed since the structure
|
|
80
|
+
* is fixed and shallow.
|
|
81
|
+
*/
|
|
82
|
+
function generateInSpecYml(baseline, options) {
|
|
83
|
+
const lines = [];
|
|
84
|
+
const meta = options?.metadata;
|
|
85
|
+
lines.push(`name: ${baseline.name}`);
|
|
86
|
+
if (baseline.title) lines.push(`title: ${baseline.title}`);
|
|
87
|
+
const maintainer = meta?.maintainer ?? baseline.maintainer;
|
|
88
|
+
if (maintainer) lines.push(`maintainer: ${maintainer}`);
|
|
89
|
+
const copyright = meta?.copyright ?? baseline.copyright;
|
|
90
|
+
if (copyright) lines.push(`copyright: ${copyright}`);
|
|
91
|
+
const license = meta?.license ?? baseline.license;
|
|
92
|
+
if (license) lines.push(`license: ${license}`);
|
|
93
|
+
if (baseline.summary) lines.push(`summary: ${baseline.summary}`);
|
|
94
|
+
const version = meta?.version ?? baseline.version;
|
|
95
|
+
if (version) lines.push(`version: '${version}'`);
|
|
96
|
+
const inspecVersion = options?.inspecVersion ?? "~>6.0";
|
|
97
|
+
lines.push(`inspec_version: '${inspecVersion}'`);
|
|
98
|
+
if (baseline.supports && baseline.supports.length > 0) {
|
|
99
|
+
lines.push("supports:");
|
|
100
|
+
for (const support of baseline.supports) {
|
|
101
|
+
const entries = [];
|
|
102
|
+
if (support.platformName) entries.push(` platform-name: ${support.platformName}`);
|
|
103
|
+
if (support.platformFamily) entries.push(` platform-family: ${support.platformFamily}`);
|
|
104
|
+
if (support.platform) entries.push(` platform: ${support.platform}`);
|
|
105
|
+
if (support.release) entries.push(` release: ${support.release}`);
|
|
106
|
+
if (entries.length > 0) {
|
|
107
|
+
lines.push(`- ${entries[0].trimStart()}`);
|
|
108
|
+
for (let i = 1; i < entries.length; i++) lines.push(entries[i]);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (baseline.depends && baseline.depends.length > 0) {
|
|
113
|
+
lines.push("depends:");
|
|
114
|
+
for (const dep of baseline.depends) {
|
|
115
|
+
const entries = [];
|
|
116
|
+
if (dep.name) entries.push(`name: ${dep.name}`);
|
|
117
|
+
if (dep.git) entries.push(`git: ${dep.git}`);
|
|
118
|
+
if (dep.url) entries.push(`url: ${dep.url}`);
|
|
119
|
+
if (dep.path) entries.push(`path: ${dep.path}`);
|
|
120
|
+
if (dep.branch) entries.push(`branch: ${dep.branch}`);
|
|
121
|
+
if (dep.compliance) entries.push(`compliance: ${dep.compliance}`);
|
|
122
|
+
if (dep.supermarket) entries.push(`supermarket: ${dep.supermarket}`);
|
|
123
|
+
if (entries.length > 0) {
|
|
124
|
+
lines.push(`- ${entries[0]}`);
|
|
125
|
+
for (let i = 1; i < entries.length; i++) lines.push(` ${entries[i]}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (baseline.inputs && baseline.inputs.length > 0) {
|
|
130
|
+
lines.push("inputs:");
|
|
131
|
+
for (const input of baseline.inputs) for (const [key, value] of Object.entries(input)) lines.push(`- ${key}: ${formatYamlValue(value)}`);
|
|
132
|
+
}
|
|
133
|
+
lines.push("");
|
|
134
|
+
return lines.join("\n");
|
|
135
|
+
}
|
|
136
|
+
/** Format a value for inline YAML output. */
|
|
137
|
+
function formatYamlValue(value) {
|
|
138
|
+
if (typeof value === "boolean") return String(value);
|
|
139
|
+
if (typeof value === "number") return String(value);
|
|
140
|
+
if (typeof value === "string") return value;
|
|
141
|
+
return JSON.stringify(value);
|
|
142
|
+
}
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/profile-generator.ts
|
|
145
|
+
/**
|
|
146
|
+
* Generate an in-memory InSpec profile from an HDF Baseline.
|
|
147
|
+
*
|
|
148
|
+
* Returns an InSpecProfile with inspec.yml content and a Map of
|
|
149
|
+
* control filenames to Ruby source code. No file I/O — the CLI
|
|
150
|
+
* is responsible for writing files to disk.
|
|
151
|
+
*/
|
|
152
|
+
function generateInSpecProfile(baseline, options) {
|
|
153
|
+
const inspecYml = generateInSpecYml(baseline, options);
|
|
154
|
+
const controls = /* @__PURE__ */ new Map();
|
|
155
|
+
if (baseline.requirements.length === 0) return {
|
|
156
|
+
inspecYml,
|
|
157
|
+
controls
|
|
158
|
+
};
|
|
159
|
+
if (options?.singleFile) {
|
|
160
|
+
const stubs = baseline.requirements.map((req) => generateControlStub(req));
|
|
161
|
+
controls.set("controls/controls.rb", stubs.join("\n"));
|
|
162
|
+
} else for (const req of baseline.requirements) {
|
|
163
|
+
const filename = `controls/${req.id.replace(/\.\./g, "").replace(/[/\\]/g, "") || "unknown"}.rb`;
|
|
164
|
+
controls.set(filename, generateControlStub(req));
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
inspecYml,
|
|
168
|
+
controls
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
//#endregion
|
|
172
|
+
export { escapeQuotes, generateControlStub, generateInSpecProfile, generateInSpecYml };
|
|
173
|
+
|
|
5
174
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/ruby-escape.ts","../src/control-stub.ts","../src/inspec-yml.ts","../src/profile-generator.ts"],"sourcesContent":["/**\n * Escape a string for use as a Ruby string literal.\n *\n * Strategy:\n * - If the string contains both single and double quotes → %q() wrapper\n * - If the string contains only single quotes → double-quoted with escaping\n * - Otherwise → single-quoted with escaping\n *\n * Ported from ts-inspec-objects escapeQuotes(), cross-referenced with\n * inspec-parser's RubyRebuilder.\n */\nexport function escapeQuotes(s: string): string {\n const hasSingle = s.includes(\"'\");\n const hasDouble = s.includes('\"');\n\n if (hasSingle && hasDouble) {\n // %q() — escape backslashes before ) so Ruby doesn't treat \\) as escaped delimiter\n return `%q(${s.replace(/\\\\\\)/g, '\\\\\\\\)')})`;\n }\n\n if (hasSingle) {\n // Double-quoted: escape backslashes, then double quotes\n return `\"${s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`;\n }\n\n // Single-quoted: escape backslashes, then single quotes\n return `'${s.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")}'`;\n}\n","import type { BaselineRequirement } from '@mitre/hdf-schema';\nimport { escapeQuotes } from './ruby-escape.js';\n\n/**\n * Generate a Ruby InSpec control stub from an HDF BaselineRequirement.\n *\n * Output follows the InSpec DSL ordering convention:\n * control 'ID' do\n * title ...\n * desc ...\n * desc 'check', ...\n * impact ...\n * tag key: value\n * <code or stub comment>\n * end\n */\nexport function generateControlStub(req: BaselineRequirement): string {\n const lines: string[] = [];\n\n lines.push(`control '${req.id}' do`);\n\n // Title\n if (req.title) {\n lines.push(` title ${escapeQuotes(req.title)}`);\n }\n\n // Descriptions: default first (as bare `desc`), then labeled\n const defaultDesc = req.descriptions.find((d) => d.label === 'default');\n if (defaultDesc) {\n lines.push(` desc ${escapeQuotes(defaultDesc.data)}`);\n }\n\n const seenDefault = new Set<string>();\n for (const d of req.descriptions) {\n if (d.label === 'default') {\n if (seenDefault.has('default')) {\n continue; // skip duplicate default\n }\n seenDefault.add('default');\n continue; // already emitted above as bare desc\n }\n lines.push(` desc '${d.label}', ${escapeQuotes(d.data)}`);\n }\n\n // Impact — always render with at least one decimal place for 0 and whole numbers\n if (req.impact !== undefined) {\n const impactStr = Number.isInteger(req.impact)\n ? req.impact.toFixed(1)\n : String(req.impact);\n lines.push(` impact ${impactStr}`);\n }\n\n // Tags\n for (const [key, value] of Object.entries(req.tags)) {\n lines.push(` ${formatTag(key, value)}`);\n }\n\n // Code body or stub placeholder\n if (req.code) {\n lines.push('');\n lines.push(req.code);\n } else {\n lines.push('');\n lines.push(' # TODO: Add InSpec test code here');\n }\n\n lines.push('end');\n lines.push(''); // trailing newline\n\n return lines.join('\\n');\n}\n\n/** Format a single tag key-value pair as Ruby DSL. */\nfunction formatTag(key: string, value: unknown): string {\n if (value === null || value === undefined) {\n return `tag ${key}: nil`;\n }\n\n if (Array.isArray(value)) {\n // Ruby array syntax: tag key: ['val1', 'val2']\n const items = value.map((v: unknown) => `'${String(v)}'`).join(', ');\n return `tag ${key}: [${items}]`;\n }\n\n if (typeof value === 'boolean') {\n return `tag ${key}: ${value}`;\n }\n\n if (typeof value === 'string') {\n return `tag ${key}: ${escapeQuotes(value)}`;\n }\n\n // Fallback for other types (numbers, objects)\n return `tag ${key}: ${JSON.stringify(value)}`;\n}\n","import type { HdfBaseline } from '@mitre/hdf-schema';\nimport type { GeneratorOptions } from './types.js';\n\n/**\n * Generate an inspec.yml YAML string from an HDF Baseline and options.\n *\n * Uses string interpolation — no YAML library needed since the structure\n * is fixed and shallow.\n */\nexport function generateInSpecYml(\n baseline: HdfBaseline,\n options?: GeneratorOptions,\n): string {\n const lines: string[] = [];\n const meta = options?.metadata;\n\n // Required: name\n lines.push(`name: ${baseline.name}`);\n\n // Optional metadata fields\n if (baseline.title) {\n lines.push(`title: ${baseline.title}`);\n }\n\n const maintainer = meta?.maintainer ?? baseline.maintainer;\n if (maintainer) {\n lines.push(`maintainer: ${maintainer}`);\n }\n\n const copyright = meta?.copyright ?? baseline.copyright;\n if (copyright) {\n lines.push(`copyright: ${copyright}`);\n }\n\n const license = meta?.license ?? baseline.license;\n if (license) {\n lines.push(`license: ${license}`);\n }\n\n if (baseline.summary) {\n lines.push(`summary: ${baseline.summary}`);\n }\n\n // Version: metadata override takes priority\n const version = meta?.version ?? baseline.version;\n if (version) {\n lines.push(`version: '${version}'`);\n }\n\n // InSpec version constraint\n const inspecVersion = options?.inspecVersion ?? '~>6.0';\n lines.push(`inspec_version: '${inspecVersion}'`);\n\n // Supports array\n if (baseline.supports && baseline.supports.length > 0) {\n lines.push('supports:');\n for (const support of baseline.supports) {\n const entries: string[] = [];\n if (support.platformName) {\n entries.push(` platform-name: ${support.platformName}`);\n }\n if (support.platformFamily) {\n entries.push(` platform-family: ${support.platformFamily}`);\n }\n if (support.platform) {\n entries.push(` platform: ${support.platform}`);\n }\n if (support.release) {\n entries.push(` release: ${support.release}`);\n }\n if (entries.length > 0) {\n lines.push(`- ${entries[0]!.trimStart()}`);\n for (let i = 1; i < entries.length; i++) {\n lines.push(entries[i]!);\n }\n }\n }\n }\n\n // Depends array\n if (baseline.depends && baseline.depends.length > 0) {\n lines.push('depends:');\n for (const dep of baseline.depends) {\n const entries: string[] = [];\n if (dep.name) entries.push(`name: ${dep.name}`);\n if (dep.git) entries.push(`git: ${dep.git}`);\n if (dep.url) entries.push(`url: ${dep.url}`);\n if (dep.path) entries.push(`path: ${dep.path}`);\n if (dep.branch) entries.push(`branch: ${dep.branch}`);\n if (dep.compliance) entries.push(`compliance: ${dep.compliance}`);\n if (dep.supermarket) entries.push(`supermarket: ${dep.supermarket}`);\n if (entries.length > 0) {\n lines.push(`- ${entries[0]}`);\n for (let i = 1; i < entries.length; i++) {\n lines.push(` ${entries[i]}`);\n }\n }\n }\n }\n\n // Inputs array\n if (baseline.inputs && baseline.inputs.length > 0) {\n lines.push('inputs:');\n for (const input of baseline.inputs) {\n for (const [key, value] of Object.entries(input)) {\n lines.push(`- ${key}: ${formatYamlValue(value)}`);\n }\n }\n }\n\n lines.push(''); // trailing newline\n return lines.join('\\n');\n}\n\n/** Format a value for inline YAML output. */\nfunction formatYamlValue(value: unknown): string {\n if (typeof value === 'boolean') return String(value);\n if (typeof value === 'number') return String(value);\n if (typeof value === 'string') return value;\n return JSON.stringify(value);\n}\n","import type { HdfBaseline } from '@mitre/hdf-schema';\nimport type { GeneratorOptions, InSpecProfile } from './types.js';\nimport { generateControlStub } from './control-stub.js';\nimport { generateInSpecYml } from './inspec-yml.js';\n\n/**\n * Generate an in-memory InSpec profile from an HDF Baseline.\n *\n * Returns an InSpecProfile with inspec.yml content and a Map of\n * control filenames to Ruby source code. No file I/O — the CLI\n * is responsible for writing files to disk.\n */\nexport function generateInSpecProfile(\n baseline: HdfBaseline,\n options?: GeneratorOptions,\n): InSpecProfile {\n const inspecYml = generateInSpecYml(baseline, options);\n const controls = new Map<string, string>();\n\n if (baseline.requirements.length === 0) {\n return { inspecYml, controls };\n }\n\n if (options?.singleFile) {\n // All controls in a single file\n const stubs = baseline.requirements.map((req) => generateControlStub(req));\n controls.set('controls/controls.rb', stubs.join('\\n'));\n } else {\n // One file per control — sanitize ID for safe filenames\n for (const req of baseline.requirements) {\n const safeId = req.id.replace(/\\.\\./g, '').replace(/[/\\\\]/g, '') || 'unknown';\n const filename = `controls/${safeId}.rb`;\n controls.set(filename, generateControlStub(req));\n }\n }\n\n return { inspecYml, controls };\n}\n"],"mappings":";;;;;;;;;;;;AAWA,SAAgB,aAAa,GAAmB;CAC9C,MAAM,YAAY,EAAE,SAAS,IAAI;CACjC,MAAM,YAAY,EAAE,SAAS,KAAI;AAEjC,KAAI,aAAa,UAEf,QAAO,MAAM,EAAE,QAAQ,SAAS,QAAQ,CAAC;AAG3C,KAAI,UAEF,QAAO,IAAI,EAAE,QAAQ,OAAO,OAAO,CAAC,QAAQ,MAAM,OAAM,CAAC;AAI3D,QAAO,IAAI,EAAE,QAAQ,OAAO,OAAO,CAAC,QAAQ,MAAM,MAAM,CAAC;;;;;;;;;;;;;;;;;ACV3D,SAAgB,oBAAoB,KAAkC;CACpE,MAAM,QAAkB,EAAE;AAE1B,OAAM,KAAK,YAAY,IAAI,GAAG,MAAM;AAGpC,KAAI,IAAI,MACN,OAAM,KAAK,WAAW,aAAa,IAAI,MAAM,GAAG;CAIlD,MAAM,cAAc,IAAI,aAAa,MAAM,MAAM,EAAE,UAAU,UAAU;AACvE,KAAI,YACF,OAAM,KAAK,UAAU,aAAa,YAAY,KAAK,GAAG;CAGxD,MAAM,8BAAc,IAAI,KAAa;AACrC,MAAK,MAAM,KAAK,IAAI,cAAc;AAChC,MAAI,EAAE,UAAU,WAAW;AACzB,OAAI,YAAY,IAAI,UAAU,CAC5B;AAEF,eAAY,IAAI,UAAU;AAC1B;;AAEF,QAAM,KAAK,WAAW,EAAE,MAAM,KAAK,aAAa,EAAE,KAAK,GAAG;;AAI5D,KAAI,IAAI,WAAW,KAAA,GAAW;EAC5B,MAAM,YAAY,OAAO,UAAU,IAAI,OAAO,GAC1C,IAAI,OAAO,QAAQ,EAAE,GACrB,OAAO,IAAI,OAAO;AACtB,QAAM,KAAK,YAAY,YAAY;;AAIrC,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,KAAK,CACjD,OAAM,KAAK,KAAK,UAAU,KAAK,MAAM,GAAG;AAI1C,KAAI,IAAI,MAAM;AACZ,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,IAAI,KAAK;QACf;AACL,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,sCAAsC;;AAGnD,OAAM,KAAK,MAAM;AACjB,OAAM,KAAK,GAAG;AAEd,QAAO,MAAM,KAAK,KAAK;;;AAIzB,SAAS,UAAU,KAAa,OAAwB;AACtD,KAAI,UAAU,QAAQ,UAAU,KAAA,EAC9B,QAAO,OAAO,IAAI;AAGpB,KAAI,MAAM,QAAQ,MAAM,CAGtB,QAAO,OAAO,IAAI,KADJ,MAAM,KAAK,MAAe,IAAI,OAAO,EAAE,CAAC,GAAG,CAAC,KAAK,KAAK,CACvC;AAG/B,KAAI,OAAO,UAAU,UACnB,QAAO,OAAO,IAAI,IAAI;AAGxB,KAAI,OAAO,UAAU,SACnB,QAAO,OAAO,IAAI,IAAI,aAAa,MAAM;AAI3C,QAAO,OAAO,IAAI,IAAI,KAAK,UAAU,MAAM;;;;;;;;;;ACpF7C,SAAgB,kBACd,UACA,SACQ;CACR,MAAM,QAAkB,EAAE;CAC1B,MAAM,OAAO,SAAS;AAGtB,OAAM,KAAK,SAAS,SAAS,OAAO;AAGpC,KAAI,SAAS,MACX,OAAM,KAAK,UAAU,SAAS,QAAQ;CAGxC,MAAM,aAAa,MAAM,cAAc,SAAS;AAChD,KAAI,WACF,OAAM,KAAK,eAAe,aAAa;CAGzC,MAAM,YAAY,MAAM,aAAa,SAAS;AAC9C,KAAI,UACF,OAAM,KAAK,cAAc,YAAY;CAGvC,MAAM,UAAU,MAAM,WAAW,SAAS;AAC1C,KAAI,QACF,OAAM,KAAK,YAAY,UAAU;AAGnC,KAAI,SAAS,QACX,OAAM,KAAK,YAAY,SAAS,UAAU;CAI5C,MAAM,UAAU,MAAM,WAAW,SAAS;AAC1C,KAAI,QACF,OAAM,KAAK,aAAa,QAAQ,GAAG;CAIrC,MAAM,gBAAgB,SAAS,iBAAiB;AAChD,OAAM,KAAK,oBAAoB,cAAc,GAAG;AAGhD,KAAI,SAAS,YAAY,SAAS,SAAS,SAAS,GAAG;AACrD,QAAM,KAAK,YAAY;AACvB,OAAK,MAAM,WAAW,SAAS,UAAU;GACvC,MAAM,UAAoB,EAAE;AAC5B,OAAI,QAAQ,aACV,SAAQ,KAAK,oBAAoB,QAAQ,eAAe;AAE1D,OAAI,QAAQ,eACV,SAAQ,KAAK,sBAAsB,QAAQ,iBAAiB;AAE9D,OAAI,QAAQ,SACV,SAAQ,KAAK,eAAe,QAAQ,WAAW;AAEjD,OAAI,QAAQ,QACV,SAAQ,KAAK,cAAc,QAAQ,UAAU;AAE/C,OAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,KAAK,KAAK,QAAQ,GAAI,WAAW,GAAG;AAC1C,SAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,IAClC,OAAM,KAAK,QAAQ,GAAI;;;;AAO/B,KAAI,SAAS,WAAW,SAAS,QAAQ,SAAS,GAAG;AACnD,QAAM,KAAK,WAAW;AACtB,OAAK,MAAM,OAAO,SAAS,SAAS;GAClC,MAAM,UAAoB,EAAE;AAC5B,OAAI,IAAI,KAAM,SAAQ,KAAK,SAAS,IAAI,OAAO;AAC/C,OAAI,IAAI,IAAK,SAAQ,KAAK,QAAQ,IAAI,MAAM;AAC5C,OAAI,IAAI,IAAK,SAAQ,KAAK,QAAQ,IAAI,MAAM;AAC5C,OAAI,IAAI,KAAM,SAAQ,KAAK,SAAS,IAAI,OAAO;AAC/C,OAAI,IAAI,OAAQ,SAAQ,KAAK,WAAW,IAAI,SAAS;AACrD,OAAI,IAAI,WAAY,SAAQ,KAAK,eAAe,IAAI,aAAa;AACjE,OAAI,IAAI,YAAa,SAAQ,KAAK,gBAAgB,IAAI,cAAc;AACpE,OAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,KAAK,KAAK,QAAQ,KAAK;AAC7B,SAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,IAClC,OAAM,KAAK,KAAK,QAAQ,KAAK;;;;AAOrC,KAAI,SAAS,UAAU,SAAS,OAAO,SAAS,GAAG;AACjD,QAAM,KAAK,UAAU;AACrB,OAAK,MAAM,SAAS,SAAS,OAC3B,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,CAC9C,OAAM,KAAK,KAAK,IAAI,IAAI,gBAAgB,MAAM,GAAG;;AAKvD,OAAM,KAAK,GAAG;AACd,QAAO,MAAM,KAAK,KAAK;;;AAIzB,SAAS,gBAAgB,OAAwB;AAC/C,KAAI,OAAO,UAAU,UAAW,QAAO,OAAO,MAAM;AACpD,KAAI,OAAO,UAAU,SAAU,QAAO,OAAO,MAAM;AACnD,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAO,KAAK,UAAU,MAAM;;;;;;;;;;;AC3G9B,SAAgB,sBACd,UACA,SACe;CACf,MAAM,YAAY,kBAAkB,UAAU,QAAQ;CACtD,MAAM,2BAAW,IAAI,KAAqB;AAE1C,KAAI,SAAS,aAAa,WAAW,EACnC,QAAO;EAAE;EAAW;EAAU;AAGhC,KAAI,SAAS,YAAY;EAEvB,MAAM,QAAQ,SAAS,aAAa,KAAK,QAAQ,oBAAoB,IAAI,CAAC;AAC1E,WAAS,IAAI,wBAAwB,MAAM,KAAK,KAAK,CAAC;OAGtD,MAAK,MAAM,OAAO,SAAS,cAAc;EAEvC,MAAM,WAAW,YADF,IAAI,GAAG,QAAQ,SAAS,GAAG,CAAC,QAAQ,UAAU,GAAG,IAAI,UAChC;AACpC,WAAS,IAAI,UAAU,oBAAoB,IAAI,CAAC;;AAIpD,QAAO;EAAE;EAAW;EAAU"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mitre/hdf-generators",
|
|
3
|
-
"version": "3.0.1",
|
|
3
|
+
"version": "3.1.0-rc.1",
|
|
4
4
|
"description": "Generate InSpec profile stubs from HDF Baseline definitions",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -10,24 +10,13 @@
|
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
|
-
"
|
|
14
|
-
"
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
18
|
"dist"
|
|
19
19
|
],
|
|
20
|
-
"scripts": {
|
|
21
|
-
"build": "pnpm clean && tsc",
|
|
22
|
-
"clean": "rimraf dist",
|
|
23
|
-
"test": "pnpm run test:ts",
|
|
24
|
-
"test:ts": "vitest run",
|
|
25
|
-
"test:watch": "vitest",
|
|
26
|
-
"test:coverage": "vitest run --coverage",
|
|
27
|
-
"type-check": "tsc --noEmit",
|
|
28
|
-
"lint": "eslint src test",
|
|
29
|
-
"lint:fix": "eslint src test --fix"
|
|
30
|
-
},
|
|
31
20
|
"repository": {
|
|
32
21
|
"type": "git",
|
|
33
22
|
"url": "https://github.com/mitre/hdf-libs.git",
|
|
@@ -36,10 +25,10 @@
|
|
|
36
25
|
"author": "MITRE Corporation",
|
|
37
26
|
"license": "Apache-2.0",
|
|
38
27
|
"dependencies": {
|
|
39
|
-
"@mitre/hdf-schema": "
|
|
28
|
+
"@mitre/hdf-schema": "^3.1.0-rc.1"
|
|
40
29
|
},
|
|
41
30
|
"engines": {
|
|
42
|
-
"node": ">=
|
|
31
|
+
"node": ">=22.0.0"
|
|
43
32
|
},
|
|
44
33
|
"keywords": [
|
|
45
34
|
"hdf",
|
|
@@ -48,5 +37,16 @@
|
|
|
48
37
|
"generator",
|
|
49
38
|
"profile",
|
|
50
39
|
"stig"
|
|
51
|
-
]
|
|
52
|
-
|
|
40
|
+
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsdown",
|
|
43
|
+
"clean": "rimraf dist",
|
|
44
|
+
"test": "pnpm run test:ts",
|
|
45
|
+
"test:ts": "vitest run",
|
|
46
|
+
"test:watch": "vitest",
|
|
47
|
+
"test:coverage": "vitest run --coverage",
|
|
48
|
+
"type-check": "tsc --noEmit",
|
|
49
|
+
"lint": "eslint src test",
|
|
50
|
+
"lint:fix": "eslint src test --fix"
|
|
51
|
+
}
|
|
52
|
+
}
|
package/dist/control-stub.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { BaselineRequirement } from '@mitre/hdf-schema';
|
|
2
|
-
/**
|
|
3
|
-
* Generate a Ruby InSpec control stub from an HDF BaselineRequirement.
|
|
4
|
-
*
|
|
5
|
-
* Output follows the InSpec DSL ordering convention:
|
|
6
|
-
* control 'ID' do
|
|
7
|
-
* title ...
|
|
8
|
-
* desc ...
|
|
9
|
-
* desc 'check', ...
|
|
10
|
-
* impact ...
|
|
11
|
-
* tag key: value
|
|
12
|
-
* <code or stub comment>
|
|
13
|
-
* end
|
|
14
|
-
*/
|
|
15
|
-
export declare function generateControlStub(req: BaselineRequirement): string;
|
|
16
|
-
//# sourceMappingURL=control-stub.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"control-stub.d.ts","sourceRoot":"","sources":["../src/control-stub.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAG7D;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,mBAAmB,GAAG,MAAM,CAsDpE"}
|
package/dist/control-stub.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { escapeQuotes } from './ruby-escape.js';
|
|
2
|
-
/**
|
|
3
|
-
* Generate a Ruby InSpec control stub from an HDF BaselineRequirement.
|
|
4
|
-
*
|
|
5
|
-
* Output follows the InSpec DSL ordering convention:
|
|
6
|
-
* control 'ID' do
|
|
7
|
-
* title ...
|
|
8
|
-
* desc ...
|
|
9
|
-
* desc 'check', ...
|
|
10
|
-
* impact ...
|
|
11
|
-
* tag key: value
|
|
12
|
-
* <code or stub comment>
|
|
13
|
-
* end
|
|
14
|
-
*/
|
|
15
|
-
export function generateControlStub(req) {
|
|
16
|
-
const lines = [];
|
|
17
|
-
lines.push(`control '${req.id}' do`);
|
|
18
|
-
// Title
|
|
19
|
-
if (req.title) {
|
|
20
|
-
lines.push(` title ${escapeQuotes(req.title)}`);
|
|
21
|
-
}
|
|
22
|
-
// Descriptions: default first (as bare `desc`), then labeled
|
|
23
|
-
const defaultDesc = req.descriptions.find((d) => d.label === 'default');
|
|
24
|
-
if (defaultDesc) {
|
|
25
|
-
lines.push(` desc ${escapeQuotes(defaultDesc.data)}`);
|
|
26
|
-
}
|
|
27
|
-
const seenDefault = new Set();
|
|
28
|
-
for (const d of req.descriptions) {
|
|
29
|
-
if (d.label === 'default') {
|
|
30
|
-
if (seenDefault.has('default')) {
|
|
31
|
-
continue; // skip duplicate default
|
|
32
|
-
}
|
|
33
|
-
seenDefault.add('default');
|
|
34
|
-
continue; // already emitted above as bare desc
|
|
35
|
-
}
|
|
36
|
-
lines.push(` desc '${d.label}', ${escapeQuotes(d.data)}`);
|
|
37
|
-
}
|
|
38
|
-
// Impact — always render with at least one decimal place for 0 and whole numbers
|
|
39
|
-
if (req.impact !== undefined) {
|
|
40
|
-
const impactStr = Number.isInteger(req.impact)
|
|
41
|
-
? req.impact.toFixed(1)
|
|
42
|
-
: String(req.impact);
|
|
43
|
-
lines.push(` impact ${impactStr}`);
|
|
44
|
-
}
|
|
45
|
-
// Tags
|
|
46
|
-
for (const [key, value] of Object.entries(req.tags)) {
|
|
47
|
-
lines.push(` ${formatTag(key, value)}`);
|
|
48
|
-
}
|
|
49
|
-
// Code body or stub placeholder
|
|
50
|
-
if (req.code) {
|
|
51
|
-
lines.push('');
|
|
52
|
-
lines.push(req.code);
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
lines.push('');
|
|
56
|
-
lines.push(' # TODO: Add InSpec test code here');
|
|
57
|
-
}
|
|
58
|
-
lines.push('end');
|
|
59
|
-
lines.push(''); // trailing newline
|
|
60
|
-
return lines.join('\n');
|
|
61
|
-
}
|
|
62
|
-
/** Format a single tag key-value pair as Ruby DSL. */
|
|
63
|
-
function formatTag(key, value) {
|
|
64
|
-
if (value === null || value === undefined) {
|
|
65
|
-
return `tag ${key}: nil`;
|
|
66
|
-
}
|
|
67
|
-
if (Array.isArray(value)) {
|
|
68
|
-
// Ruby array syntax: tag key: ['val1', 'val2']
|
|
69
|
-
const items = value.map((v) => `'${String(v)}'`).join(', ');
|
|
70
|
-
return `tag ${key}: [${items}]`;
|
|
71
|
-
}
|
|
72
|
-
if (typeof value === 'boolean') {
|
|
73
|
-
return `tag ${key}: ${value}`;
|
|
74
|
-
}
|
|
75
|
-
if (typeof value === 'string') {
|
|
76
|
-
return `tag ${key}: ${escapeQuotes(value)}`;
|
|
77
|
-
}
|
|
78
|
-
// Fallback for other types (numbers, objects)
|
|
79
|
-
return `tag ${key}: ${JSON.stringify(value)}`;
|
|
80
|
-
}
|
|
81
|
-
//# sourceMappingURL=control-stub.js.map
|
package/dist/control-stub.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"control-stub.js","sourceRoot":"","sources":["../src/control-stub.ts"],"names":[],"mappings":"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"}
|
package/dist/inspec-yml.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { HdfBaseline } from '@mitre/hdf-schema';
|
|
2
|
-
import type { GeneratorOptions } from './types.js';
|
|
3
|
-
/**
|
|
4
|
-
* Generate an inspec.yml YAML string from an HDF Baseline and options.
|
|
5
|
-
*
|
|
6
|
-
* Uses string interpolation — no YAML library needed since the structure
|
|
7
|
-
* is fixed and shallow.
|
|
8
|
-
*/
|
|
9
|
-
export declare function generateInSpecYml(baseline: HdfBaseline, options?: GeneratorOptions): string;
|
|
10
|
-
//# sourceMappingURL=inspec-yml.d.ts.map
|
package/dist/inspec-yml.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inspec-yml.d.ts","sourceRoot":"","sources":["../src/inspec-yml.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,WAAW,EACrB,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,CAoGR"}
|
package/dist/inspec-yml.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generate an inspec.yml YAML string from an HDF Baseline and options.
|
|
3
|
-
*
|
|
4
|
-
* Uses string interpolation — no YAML library needed since the structure
|
|
5
|
-
* is fixed and shallow.
|
|
6
|
-
*/
|
|
7
|
-
export function generateInSpecYml(baseline, options) {
|
|
8
|
-
const lines = [];
|
|
9
|
-
const meta = options?.metadata;
|
|
10
|
-
// Required: name
|
|
11
|
-
lines.push(`name: ${baseline.name}`);
|
|
12
|
-
// Optional metadata fields
|
|
13
|
-
if (baseline.title) {
|
|
14
|
-
lines.push(`title: ${baseline.title}`);
|
|
15
|
-
}
|
|
16
|
-
const maintainer = meta?.maintainer ?? baseline.maintainer;
|
|
17
|
-
if (maintainer) {
|
|
18
|
-
lines.push(`maintainer: ${maintainer}`);
|
|
19
|
-
}
|
|
20
|
-
const copyright = meta?.copyright ?? baseline.copyright;
|
|
21
|
-
if (copyright) {
|
|
22
|
-
lines.push(`copyright: ${copyright}`);
|
|
23
|
-
}
|
|
24
|
-
const license = meta?.license ?? baseline.license;
|
|
25
|
-
if (license) {
|
|
26
|
-
lines.push(`license: ${license}`);
|
|
27
|
-
}
|
|
28
|
-
if (baseline.summary) {
|
|
29
|
-
lines.push(`summary: ${baseline.summary}`);
|
|
30
|
-
}
|
|
31
|
-
// Version: metadata override takes priority
|
|
32
|
-
const version = meta?.version ?? baseline.version;
|
|
33
|
-
if (version) {
|
|
34
|
-
lines.push(`version: '${version}'`);
|
|
35
|
-
}
|
|
36
|
-
// InSpec version constraint
|
|
37
|
-
const inspecVersion = options?.inspecVersion ?? '~>6.0';
|
|
38
|
-
lines.push(`inspec_version: '${inspecVersion}'`);
|
|
39
|
-
// Supports array
|
|
40
|
-
if (baseline.supports && baseline.supports.length > 0) {
|
|
41
|
-
lines.push('supports:');
|
|
42
|
-
for (const support of baseline.supports) {
|
|
43
|
-
const entries = [];
|
|
44
|
-
if (support.platformName) {
|
|
45
|
-
entries.push(` platform-name: ${support.platformName}`);
|
|
46
|
-
}
|
|
47
|
-
if (support.platformFamily) {
|
|
48
|
-
entries.push(` platform-family: ${support.platformFamily}`);
|
|
49
|
-
}
|
|
50
|
-
if (support.platform) {
|
|
51
|
-
entries.push(` platform: ${support.platform}`);
|
|
52
|
-
}
|
|
53
|
-
if (support.release) {
|
|
54
|
-
entries.push(` release: ${support.release}`);
|
|
55
|
-
}
|
|
56
|
-
if (entries.length > 0) {
|
|
57
|
-
lines.push(`- ${entries[0].trimStart()}`);
|
|
58
|
-
for (let i = 1; i < entries.length; i++) {
|
|
59
|
-
lines.push(entries[i]);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
// Depends array
|
|
65
|
-
if (baseline.depends && baseline.depends.length > 0) {
|
|
66
|
-
lines.push('depends:');
|
|
67
|
-
for (const dep of baseline.depends) {
|
|
68
|
-
const entries = [];
|
|
69
|
-
if (dep.name)
|
|
70
|
-
entries.push(`name: ${dep.name}`);
|
|
71
|
-
if (dep.git)
|
|
72
|
-
entries.push(`git: ${dep.git}`);
|
|
73
|
-
if (dep.url)
|
|
74
|
-
entries.push(`url: ${dep.url}`);
|
|
75
|
-
if (dep.path)
|
|
76
|
-
entries.push(`path: ${dep.path}`);
|
|
77
|
-
if (dep.branch)
|
|
78
|
-
entries.push(`branch: ${dep.branch}`);
|
|
79
|
-
if (dep.compliance)
|
|
80
|
-
entries.push(`compliance: ${dep.compliance}`);
|
|
81
|
-
if (dep.supermarket)
|
|
82
|
-
entries.push(`supermarket: ${dep.supermarket}`);
|
|
83
|
-
if (entries.length > 0) {
|
|
84
|
-
lines.push(`- ${entries[0]}`);
|
|
85
|
-
for (let i = 1; i < entries.length; i++) {
|
|
86
|
-
lines.push(` ${entries[i]}`);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
// Inputs array
|
|
92
|
-
if (baseline.inputs && baseline.inputs.length > 0) {
|
|
93
|
-
lines.push('inputs:');
|
|
94
|
-
for (const input of baseline.inputs) {
|
|
95
|
-
for (const [key, value] of Object.entries(input)) {
|
|
96
|
-
lines.push(`- ${key}: ${formatYamlValue(value)}`);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
lines.push(''); // trailing newline
|
|
101
|
-
return lines.join('\n');
|
|
102
|
-
}
|
|
103
|
-
/** Format a value for inline YAML output. */
|
|
104
|
-
function formatYamlValue(value) {
|
|
105
|
-
if (typeof value === 'boolean')
|
|
106
|
-
return String(value);
|
|
107
|
-
if (typeof value === 'number')
|
|
108
|
-
return String(value);
|
|
109
|
-
if (typeof value === 'string')
|
|
110
|
-
return value;
|
|
111
|
-
return JSON.stringify(value);
|
|
112
|
-
}
|
|
113
|
-
//# sourceMappingURL=inspec-yml.js.map
|
package/dist/inspec-yml.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inspec-yml.js","sourceRoot":"","sources":["../src/inspec-yml.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { HdfBaseline } from '@mitre/hdf-schema';
|
|
2
|
-
import type { GeneratorOptions, InSpecProfile } from './types.js';
|
|
3
|
-
/**
|
|
4
|
-
* Generate an in-memory InSpec profile from an HDF Baseline.
|
|
5
|
-
*
|
|
6
|
-
* Returns an InSpecProfile with inspec.yml content and a Map of
|
|
7
|
-
* control filenames to Ruby source code. No file I/O — the CLI
|
|
8
|
-
* is responsible for writing files to disk.
|
|
9
|
-
*/
|
|
10
|
-
export declare function generateInSpecProfile(baseline: HdfBaseline, options?: GeneratorOptions): InSpecProfile;
|
|
11
|
-
//# sourceMappingURL=profile-generator.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"profile-generator.d.ts","sourceRoot":"","sources":["../src/profile-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIlE;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,WAAW,EACrB,OAAO,CAAC,EAAE,gBAAgB,GACzB,aAAa,CAsBf"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { generateControlStub } from './control-stub.js';
|
|
2
|
-
import { generateInSpecYml } from './inspec-yml.js';
|
|
3
|
-
/**
|
|
4
|
-
* Generate an in-memory InSpec profile from an HDF Baseline.
|
|
5
|
-
*
|
|
6
|
-
* Returns an InSpecProfile with inspec.yml content and a Map of
|
|
7
|
-
* control filenames to Ruby source code. No file I/O — the CLI
|
|
8
|
-
* is responsible for writing files to disk.
|
|
9
|
-
*/
|
|
10
|
-
export function generateInSpecProfile(baseline, options) {
|
|
11
|
-
const inspecYml = generateInSpecYml(baseline, options);
|
|
12
|
-
const controls = new Map();
|
|
13
|
-
if (baseline.requirements.length === 0) {
|
|
14
|
-
return { inspecYml, controls };
|
|
15
|
-
}
|
|
16
|
-
if (options?.singleFile) {
|
|
17
|
-
// All controls in a single file
|
|
18
|
-
const stubs = baseline.requirements.map((req) => generateControlStub(req));
|
|
19
|
-
controls.set('controls/controls.rb', stubs.join('\n'));
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
// One file per control — sanitize ID for safe filenames
|
|
23
|
-
for (const req of baseline.requirements) {
|
|
24
|
-
const safeId = req.id.replace(/\.\./g, '').replace(/[/\\]/g, '') || 'unknown';
|
|
25
|
-
const filename = `controls/${safeId}.rb`;
|
|
26
|
-
controls.set(filename, generateControlStub(req));
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return { inspecYml, controls };
|
|
30
|
-
}
|
|
31
|
-
//# sourceMappingURL=profile-generator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"profile-generator.js","sourceRoot":"","sources":["../src/profile-generator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAqB,EACrB,OAA0B;IAE1B,MAAM,SAAS,GAAG,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE3C,IAAI,QAAQ,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;IACjC,CAAC;IAED,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;QACxB,gCAAgC;QAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3E,QAAQ,CAAC,GAAG,CAAC,sBAAsB,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACzD,CAAC;SAAM,CAAC;QACN,wDAAwD;QACxD,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC;YAC9E,MAAM,QAAQ,GAAG,YAAY,MAAM,KAAK,CAAC;YACzC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;AACjC,CAAC"}
|
package/dist/ruby-escape.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Escape a string for use as a Ruby string literal.
|
|
3
|
-
*
|
|
4
|
-
* Strategy:
|
|
5
|
-
* - If the string contains both single and double quotes → %q() wrapper
|
|
6
|
-
* - If the string contains only single quotes → double-quoted with escaping
|
|
7
|
-
* - Otherwise → single-quoted with escaping
|
|
8
|
-
*
|
|
9
|
-
* Ported from ts-inspec-objects escapeQuotes(), cross-referenced with
|
|
10
|
-
* inspec-parser's RubyRebuilder.
|
|
11
|
-
*/
|
|
12
|
-
export declare function escapeQuotes(s: string): string;
|
|
13
|
-
//# sourceMappingURL=ruby-escape.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ruby-escape.d.ts","sourceRoot":"","sources":["../src/ruby-escape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAgB9C"}
|
package/dist/ruby-escape.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Escape a string for use as a Ruby string literal.
|
|
3
|
-
*
|
|
4
|
-
* Strategy:
|
|
5
|
-
* - If the string contains both single and double quotes → %q() wrapper
|
|
6
|
-
* - If the string contains only single quotes → double-quoted with escaping
|
|
7
|
-
* - Otherwise → single-quoted with escaping
|
|
8
|
-
*
|
|
9
|
-
* Ported from ts-inspec-objects escapeQuotes(), cross-referenced with
|
|
10
|
-
* inspec-parser's RubyRebuilder.
|
|
11
|
-
*/
|
|
12
|
-
export function escapeQuotes(s) {
|
|
13
|
-
const hasSingle = s.includes("'");
|
|
14
|
-
const hasDouble = s.includes('"');
|
|
15
|
-
if (hasSingle && hasDouble) {
|
|
16
|
-
// %q() — escape backslashes before ) so Ruby doesn't treat \) as escaped delimiter
|
|
17
|
-
return `%q(${s.replace(/\\\)/g, '\\\\)')})`;
|
|
18
|
-
}
|
|
19
|
-
if (hasSingle) {
|
|
20
|
-
// Double-quoted: escape backslashes, then double quotes
|
|
21
|
-
return `"${s.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
22
|
-
}
|
|
23
|
-
// Single-quoted: escape backslashes, then single quotes
|
|
24
|
-
return `'${s.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`;
|
|
25
|
-
}
|
|
26
|
-
//# sourceMappingURL=ruby-escape.js.map
|
package/dist/ruby-escape.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ruby-escape.js","sourceRoot":"","sources":["../src/ruby-escape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,MAAM,SAAS,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,SAAS,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAElC,IAAI,SAAS,IAAI,SAAS,EAAE,CAAC;QAC3B,mFAAmF;QACnF,OAAO,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC;IAC9C,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,wDAAwD;QACxD,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;IAC9D,CAAC;IAED,wDAAwD;IACxD,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;AAC9D,CAAC"}
|
package/dist/types.d.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Options for controlling InSpec profile generation.
|
|
3
|
-
*/
|
|
4
|
-
export interface GeneratorOptions {
|
|
5
|
-
/** Put all controls in a single controls.rb file instead of one file per control. */
|
|
6
|
-
singleFile?: boolean;
|
|
7
|
-
/** Override baseline metadata in the generated inspec.yml. */
|
|
8
|
-
metadata?: ProfileMetadata;
|
|
9
|
-
/** InSpec version constraint for inspec.yml. Default: '~>6.0'. */
|
|
10
|
-
inspecVersion?: string;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Metadata overrides for the generated inspec.yml.
|
|
14
|
-
*/
|
|
15
|
-
export interface ProfileMetadata {
|
|
16
|
-
maintainer?: string;
|
|
17
|
-
copyright?: string;
|
|
18
|
-
license?: string;
|
|
19
|
-
version?: string;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* An in-memory InSpec profile. No file I/O — the CLI is responsible for writing.
|
|
23
|
-
*/
|
|
24
|
-
export interface InSpecProfile {
|
|
25
|
-
/** The inspec.yml content as a YAML string. */
|
|
26
|
-
inspecYml: string;
|
|
27
|
-
/** Map of filename (e.g. 'controls/SV-238196.rb') to Ruby source code. */
|
|
28
|
-
controls: Map<string, string>;
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,qFAAqF;IACrF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B"}
|
package/dist/types.js
DELETED
package/dist/types.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|