@secretgenerator/cli 2.0.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/README.md +89 -0
- package/dist/install.js +158 -0
- package/dist/install.js.map +1 -0
- package/dist/platform.js +45 -0
- package/dist/platform.js.map +1 -0
- package/dist/run.js +68 -0
- package/dist/run.js.map +1 -0
- package/dist/verify.js +94 -0
- package/dist/verify.js.map +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# @secretgenerator/cli
|
|
2
|
+
|
|
3
|
+
Zero-config installer for the [secretgenerator](https://secretgenerator.org)
|
|
4
|
+
CLI. Downloads the right prebuilt binary for your OS and architecture from a
|
|
5
|
+
verified GitHub release, checks the SHA-256, and (when `cosign` is on PATH)
|
|
6
|
+
verifies the keyless Sigstore signature.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
# One-off invocation, no global install:
|
|
12
|
+
npx secretgenerator --json -n 24
|
|
13
|
+
|
|
14
|
+
# Project-local:
|
|
15
|
+
npm install --save-dev @secretgenerator/cli
|
|
16
|
+
|
|
17
|
+
# Global:
|
|
18
|
+
npm install -g @secretgenerator/cli
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The first invocation downloads the binary (~2 MB) for your platform and caches
|
|
22
|
+
it inside the package. Subsequent calls execute the cached binary directly —
|
|
23
|
+
zero startup overhead.
|
|
24
|
+
|
|
25
|
+
## Why prefer this over `go install`?
|
|
26
|
+
|
|
27
|
+
- **Zero Go toolchain required.** `go install` works only if the user has a Go
|
|
28
|
+
compiler matching the project's minimum version installed.
|
|
29
|
+
- **Verified by default.** SHA-256 + (when available) cosign keyless signature
|
|
30
|
+
validate the binary against the published Sigstore transparency log entry.
|
|
31
|
+
- **Pinned per release.** The npm package version mirrors the secretgenerator
|
|
32
|
+
CLI tag, so `npm install @secretgenerator/cli@2.0.0` always pulls the exact
|
|
33
|
+
signed v2.0.0 binary.
|
|
34
|
+
- **AI-agent-friendly.** Agents writing Node/TypeScript prefer `npx X`. This
|
|
35
|
+
wrapper makes secretgenerator a drop-in replacement for `crypto.randomUUID`
|
|
36
|
+
and `crypto.randomBytes` in agent-generated scaffolding.
|
|
37
|
+
|
|
38
|
+
## Verification chain
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
You ─trust─▶ Sigstore Fulcio root
|
|
42
|
+
│
|
|
43
|
+
└─signs cert tied to─▶ GitHub Actions OIDC identity
|
|
44
|
+
│
|
|
45
|
+
└─signs─▶ checksums.txt
|
|
46
|
+
│
|
|
47
|
+
└─pins SHA-256 of─▶ archive
|
|
48
|
+
│
|
|
49
|
+
└─contains─▶ binary you run
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
If `cosign` is not installed, the package still verifies the SHA-256 against
|
|
53
|
+
the same `checksums.txt` (downloaded from the same HTTPS GitHub host that
|
|
54
|
+
signed it). To upgrade to the strongest tier, install cosign:
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
brew install cosign # macOS
|
|
58
|
+
# or: https://docs.sigstore.dev/cosign/installation
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
When cosign is available the postinstall step verifies that `checksums.txt`
|
|
62
|
+
was signed by the secretgenerator GitHub Actions release workflow, validating
|
|
63
|
+
the certificate identity against
|
|
64
|
+
`https://github.com/rafaelperoco/secretgenerator/.github/workflows/release.yml@refs/tags/v.*`.
|
|
65
|
+
|
|
66
|
+
## Environment overrides
|
|
67
|
+
|
|
68
|
+
| Variable | Effect |
|
|
69
|
+
| --------------------------------- | ----------------------------------------------------------------- |
|
|
70
|
+
| `SECRETGENERATOR_VERSION` | Pin a specific release tag, overriding the package's own version. |
|
|
71
|
+
| `SECRETGENERATOR_SKIP_DOWNLOAD=1` | Skip postinstall download (for offline CI / tarball-only flows). |
|
|
72
|
+
|
|
73
|
+
## Supported platforms
|
|
74
|
+
|
|
75
|
+
| OS | Architectures |
|
|
76
|
+
| ------- | --------------- |
|
|
77
|
+
| Linux | x64, arm64 |
|
|
78
|
+
| macOS | x64, arm64 |
|
|
79
|
+
| Windows | x64 |
|
|
80
|
+
|
|
81
|
+
For other platforms, install from source:
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
go install github.com/rafaelperoco/secretgenerator/cmd/secretgenerator@latest
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## License
|
|
88
|
+
|
|
89
|
+
MIT. Source: [github.com/rafaelperoco/secretgenerator](https://github.com/rafaelperoco/secretgenerator).
|
package/dist/install.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// postinstall hook: download the secretgenerator binary for the current
|
|
3
|
+
// platform, verify its integrity, extract it next to dist/run.js so the
|
|
4
|
+
// `bin` entry can exec it directly.
|
|
5
|
+
//
|
|
6
|
+
// Download steps (each fails fast with a clear message):
|
|
7
|
+
// 1. Determine the right release version (env override or package.json).
|
|
8
|
+
// 2. Compute archive name + URL.
|
|
9
|
+
// 3. Fetch the archive, checksums.txt, checksums.txt.sig, checksums.txt.pem.
|
|
10
|
+
// 4. Verify the archive's SHA-256 against checksums.txt.
|
|
11
|
+
// 5. (Optional) Verify cosign keyless signature on checksums.txt.
|
|
12
|
+
// 6. Extract the binary, drop it at <packageRoot>/bin/<binary>.
|
|
13
|
+
// 7. Save a marker file at <packageRoot>/bin/.installed so run.js can
|
|
14
|
+
// detect a successful install on subsequent invocations.
|
|
15
|
+
import { createWriteStream, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
|
|
16
|
+
import { createReadStream } from "node:fs";
|
|
17
|
+
import { mkdtempSync } from "node:fs";
|
|
18
|
+
import { tmpdir } from "node:os";
|
|
19
|
+
import path from "node:path";
|
|
20
|
+
import { fileURLToPath } from "node:url";
|
|
21
|
+
import { spawnSync } from "node:child_process";
|
|
22
|
+
import { Readable } from "node:stream";
|
|
23
|
+
import { pipeline } from "node:stream/promises";
|
|
24
|
+
import { detectAsset, UnsupportedPlatformError } from "./platform.js";
|
|
25
|
+
import { cosignAvailable, verifyChecksum, verifyCosign, IntegrityError, } from "./verify.js";
|
|
26
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
27
|
+
// dist/install.js is in `cli/dist/`, packageRoot is `cli/`.
|
|
28
|
+
const packageRoot = path.resolve(__dirname, "..");
|
|
29
|
+
const binDir = path.join(packageRoot, "bin");
|
|
30
|
+
const installedMarker = path.join(binDir, ".installed");
|
|
31
|
+
const REPO = "rafaelperoco/secretgenerator";
|
|
32
|
+
main().catch((err) => {
|
|
33
|
+
// Do not exit 1 — that would block `npm install` for legitimate users
|
|
34
|
+
// (CI environments without network, npm install in tarball-only mode,
|
|
35
|
+
// etc.). Print a clear error so the user can retry on first run.
|
|
36
|
+
console.error(`[secretgenerator] install failed: ${err.message}`);
|
|
37
|
+
console.error(`[secretgenerator] you can retry by running \`npx secretgenerator --version\`, ` +
|
|
38
|
+
`or install manually from ${`https://github.com/${REPO}/releases/latest`}.`);
|
|
39
|
+
process.exit(0);
|
|
40
|
+
});
|
|
41
|
+
async function main() {
|
|
42
|
+
if (process.env.SECRETGENERATOR_SKIP_DOWNLOAD === "1") {
|
|
43
|
+
console.log("[secretgenerator] SECRETGENERATOR_SKIP_DOWNLOAD=1; skipping postinstall");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
let asset;
|
|
47
|
+
try {
|
|
48
|
+
asset = detectAsset();
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
if (err instanceof UnsupportedPlatformError) {
|
|
52
|
+
console.warn(`[secretgenerator] ${err.message}`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
const version = readVersion();
|
|
58
|
+
const archiveName = `secretgenerator_${stripV(version)}_${asset.suffix}`;
|
|
59
|
+
const baseUrl = `https://github.com/${REPO}/releases/download/${version}`;
|
|
60
|
+
const archiveUrl = `${baseUrl}/${archiveName}`;
|
|
61
|
+
const checksumsUrl = `${baseUrl}/checksums.txt`;
|
|
62
|
+
const sigUrl = `${baseUrl}/checksums.txt.sig`;
|
|
63
|
+
const pemUrl = `${baseUrl}/checksums.txt.pem`;
|
|
64
|
+
console.log(`[secretgenerator] downloading ${archiveName}`);
|
|
65
|
+
const work = mkdtempSync(path.join(tmpdir(), "secretgen-install-"));
|
|
66
|
+
try {
|
|
67
|
+
const archivePath = path.join(work, archiveName);
|
|
68
|
+
const checksumsPath = path.join(work, "checksums.txt");
|
|
69
|
+
const sigPath = path.join(work, "checksums.txt.sig");
|
|
70
|
+
const pemPath = path.join(work, "checksums.txt.pem");
|
|
71
|
+
await Promise.all([
|
|
72
|
+
download(archiveUrl, archivePath),
|
|
73
|
+
download(checksumsUrl, checksumsPath),
|
|
74
|
+
download(sigUrl, sigPath, { allowMissing: true }),
|
|
75
|
+
download(pemUrl, pemPath, { allowMissing: true }),
|
|
76
|
+
]);
|
|
77
|
+
const checksumsText = readFileSync(checksumsPath, "utf8");
|
|
78
|
+
verifyChecksum(archivePath, archiveName, checksumsText);
|
|
79
|
+
console.log(`[secretgenerator] SHA-256 verified for ${archiveName}`);
|
|
80
|
+
if (existsSync(sigPath) && existsSync(pemPath) && cosignAvailable()) {
|
|
81
|
+
if (verifyCosign(checksumsPath, pemPath, sigPath)) {
|
|
82
|
+
console.log("[secretgenerator] cosign keyless signature verified (Sigstore/Fulcio)");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else if (!cosignAvailable()) {
|
|
86
|
+
console.log("[secretgenerator] cosign not on PATH; skipped Sigstore signature check (SHA-256 still verified)");
|
|
87
|
+
}
|
|
88
|
+
mkdirSync(binDir, { recursive: true });
|
|
89
|
+
extract(archivePath, binDir, asset.format);
|
|
90
|
+
const binPath = path.join(binDir, asset.binary);
|
|
91
|
+
if (!existsSync(binPath)) {
|
|
92
|
+
throw new IntegrityError(`archive ${archiveName} did not contain ${asset.binary} after extraction`);
|
|
93
|
+
}
|
|
94
|
+
if (process.platform !== "win32") {
|
|
95
|
+
// Mark executable.
|
|
96
|
+
const fs = await import("node:fs");
|
|
97
|
+
fs.chmodSync(binPath, 0o755);
|
|
98
|
+
}
|
|
99
|
+
writeFileSync(installedMarker, JSON.stringify({ version, asset: asset.suffix, installedAt: new Date().toISOString() }));
|
|
100
|
+
console.log(`[secretgenerator] installed ${binPath} (release ${version})`);
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
try {
|
|
104
|
+
rmSync(work, { recursive: true, force: true });
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// tempdir cleanup is best-effort
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function readVersion() {
|
|
112
|
+
// Allow override (used by smoke tests pinning a specific tag).
|
|
113
|
+
if (process.env.SECRETGENERATOR_VERSION) {
|
|
114
|
+
return process.env.SECRETGENERATOR_VERSION;
|
|
115
|
+
}
|
|
116
|
+
const pkg = JSON.parse(readFileSync(path.join(packageRoot, "package.json"), "utf8"));
|
|
117
|
+
return `v${pkg.version}`;
|
|
118
|
+
}
|
|
119
|
+
function stripV(v) {
|
|
120
|
+
return v.startsWith("v") ? v.slice(1) : v;
|
|
121
|
+
}
|
|
122
|
+
async function download(url, out, opts = {}) {
|
|
123
|
+
const res = await fetch(url, { redirect: "follow" });
|
|
124
|
+
if (res.status === 404 && opts.allowMissing) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (!res.ok || !res.body) {
|
|
128
|
+
throw new Error(`download ${url} -> HTTP ${res.status}`);
|
|
129
|
+
}
|
|
130
|
+
const nodeStream = Readable.fromWeb(res.body);
|
|
131
|
+
await pipeline(nodeStream, createWriteStream(out));
|
|
132
|
+
}
|
|
133
|
+
function extract(archive, dest, format) {
|
|
134
|
+
if (format === "tar.gz") {
|
|
135
|
+
const r = spawnSync("tar", ["-xzf", archive, "-C", dest], {
|
|
136
|
+
stdio: "inherit",
|
|
137
|
+
});
|
|
138
|
+
if (r.status !== 0)
|
|
139
|
+
throw new Error(`tar exit ${r.status}`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
// zip — use Node's built-in zlib + a small inflate; the simplest cross-
|
|
143
|
+
// platform approach on Windows is `tar -xf` which Windows 10+ ships
|
|
144
|
+
// with. Fall back to PowerShell Expand-Archive if tar is missing.
|
|
145
|
+
const r = spawnSync("tar", ["-xf", archive, "-C", dest], {
|
|
146
|
+
stdio: "inherit",
|
|
147
|
+
});
|
|
148
|
+
if (r.status !== 0) {
|
|
149
|
+
const ps = spawnSync("powershell", ["-Command", `Expand-Archive -Path '${archive}' -DestinationPath '${dest}' -Force`], { stdio: "inherit" });
|
|
150
|
+
if (ps.status !== 0) {
|
|
151
|
+
throw new Error("zip extraction failed: tar and Expand-Archive both errored");
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Reading the archive is delegated to `tar` / `Expand-Archive`; the
|
|
156
|
+
// pipeline-and-stream imports above are kept because download() uses them.
|
|
157
|
+
void createReadStream;
|
|
158
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"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"}
|
package/dist/platform.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Maps Node's process.platform / process.arch to the asset filenames
|
|
2
|
+
// goreleaser produces for secretgenerator releases. The mapping must match
|
|
3
|
+
// .goreleaser.yaml's archive name template:
|
|
4
|
+
// {{.ProjectName}}_{{.Version}}_{{.Os}}_{{.Arch}}.{tar.gz|zip}
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
export class UnsupportedPlatformError extends Error {
|
|
7
|
+
constructor(platform, arch) {
|
|
8
|
+
super(`secretgenerator: no prebuilt release for ${platform}/${arch}. ` +
|
|
9
|
+
"Supported: linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64. " +
|
|
10
|
+
"If your platform is unsupported, install from source via " +
|
|
11
|
+
"`go install github.com/rafaelperoco/secretgenerator/cmd/secretgenerator@latest`.");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function detectAsset() {
|
|
15
|
+
const platform = process.platform;
|
|
16
|
+
const arch = process.arch;
|
|
17
|
+
switch (`${platform}/${arch}`) {
|
|
18
|
+
case "linux/x64":
|
|
19
|
+
return { suffix: "linux_amd64.tar.gz", format: "tar.gz", binary: "secretgenerator" };
|
|
20
|
+
case "linux/arm64":
|
|
21
|
+
return { suffix: "linux_arm64.tar.gz", format: "tar.gz", binary: "secretgenerator" };
|
|
22
|
+
case "darwin/x64":
|
|
23
|
+
return { suffix: "darwin_amd64.tar.gz", format: "tar.gz", binary: "secretgenerator" };
|
|
24
|
+
case "darwin/arm64":
|
|
25
|
+
return { suffix: "darwin_arm64.tar.gz", format: "tar.gz", binary: "secretgenerator" };
|
|
26
|
+
case "win32/x64":
|
|
27
|
+
return { suffix: "windows_amd64.zip", format: "zip", binary: "secretgenerator.exe" };
|
|
28
|
+
default:
|
|
29
|
+
throw new UnsupportedPlatformError(platform, arch);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** Where the downloaded binary is cached on disk. Honors NPM-style local
|
|
33
|
+
* install layouts (the npm package's own dir) since postinstall runs there. */
|
|
34
|
+
export function cacheDir(packageRoot) {
|
|
35
|
+
return packageRoot;
|
|
36
|
+
}
|
|
37
|
+
export function homedirSafe() {
|
|
38
|
+
try {
|
|
39
|
+
return os.homedir();
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return "/tmp";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,2EAA2E;AAC3E,4CAA4C;AAC5C,iEAAiE;AAEjE,OAAO,EAAE,MAAM,SAAS,CAAC;AAWzB,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IACjD,YAAY,QAAgB,EAAE,IAAY;QACxC,KAAK,CACH,4CAA4C,QAAQ,IAAI,IAAI,IAAI;YAC9D,kFAAkF;YAClF,2DAA2D;YAC3D,kFAAkF,CACrF,CAAC;IACJ,CAAC;CACF;AAED,MAAM,UAAU,WAAW;IACzB,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC1B,QAAQ,GAAG,QAAQ,IAAI,IAAI,EAAE,EAAE,CAAC;QAC9B,KAAK,WAAW;YACd,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;QACvF,KAAK,aAAa;YAChB,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;QACvF,KAAK,YAAY;YACf,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;QACxF,KAAK,cAAc;YACjB,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;QACxF,KAAK,WAAW;YACd,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC;QACvF;YACE,MAAM,IAAI,wBAAwB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACvD,CAAC;AACH,CAAC;AAED;+EAC+E;AAC/E,MAAM,UAAU,QAAQ,CAAC,WAAmB;IAC1C,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC;IAChB,CAAC;AACH,CAAC"}
|
package/dist/run.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// `npx secretgenerator <args>` entry point.
|
|
3
|
+
//
|
|
4
|
+
// On first run after install, the binary lives at <packageRoot>/bin/.
|
|
5
|
+
// This wrapper simply execs it with the user's argv. We pass the user's
|
|
6
|
+
// stdio through unchanged so JSON pipelines, audit logs, and TTY-aware
|
|
7
|
+
// behavior all work transparently.
|
|
8
|
+
//
|
|
9
|
+
// If the postinstall step did not run (some npm install configurations,
|
|
10
|
+
// CI containers without network), we fall back to invoking install on
|
|
11
|
+
// demand the first time the binary is missing. This makes the package
|
|
12
|
+
// resilient to npm's `--ignore-scripts`.
|
|
13
|
+
import { spawn } from "node:child_process";
|
|
14
|
+
import { existsSync } from "node:fs";
|
|
15
|
+
import path from "node:path";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
import { detectAsset, UnsupportedPlatformError } from "./platform.js";
|
|
18
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const packageRoot = path.resolve(__dirname, "..");
|
|
20
|
+
const binDir = path.join(packageRoot, "bin");
|
|
21
|
+
main().catch((err) => {
|
|
22
|
+
console.error(`secretgenerator: ${err.message}`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
});
|
|
25
|
+
async function main() {
|
|
26
|
+
let asset;
|
|
27
|
+
try {
|
|
28
|
+
asset = detectAsset();
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
if (err instanceof UnsupportedPlatformError) {
|
|
32
|
+
console.error(err.message);
|
|
33
|
+
process.exit(2);
|
|
34
|
+
}
|
|
35
|
+
throw err;
|
|
36
|
+
}
|
|
37
|
+
const binary = path.join(binDir, asset.binary);
|
|
38
|
+
if (!existsSync(binary)) {
|
|
39
|
+
// Lazy install: --ignore-scripts users only pay the cost on first run.
|
|
40
|
+
console.error("[secretgenerator] binary not found; running install (this happens once per machine)");
|
|
41
|
+
const installScript = path.join(__dirname, "install.js");
|
|
42
|
+
await runChild(process.execPath, [installScript], "inherit");
|
|
43
|
+
if (!existsSync(binary)) {
|
|
44
|
+
throw new Error(`binary still missing at ${binary} after install; check earlier output for the reason`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const status = await runChild(binary, process.argv.slice(2), "inherit");
|
|
48
|
+
process.exit(status);
|
|
49
|
+
}
|
|
50
|
+
function runChild(cmd, args, stdio) {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
const child = spawn(cmd, args, {
|
|
53
|
+
stdio,
|
|
54
|
+
// Forward signals so Ctrl-C in npx propagates to the child.
|
|
55
|
+
windowsHide: true,
|
|
56
|
+
});
|
|
57
|
+
child.on("error", reject);
|
|
58
|
+
child.on("exit", (code, signal) => {
|
|
59
|
+
if (signal) {
|
|
60
|
+
// Re-raise the signal to the parent so shell-level exit code
|
|
61
|
+
// semantics (130 for SIGINT, etc.) are preserved.
|
|
62
|
+
process.kill(process.pid, signal);
|
|
63
|
+
}
|
|
64
|
+
resolve(code ?? 0);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=run.js.map
|
package/dist/run.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
|
package/dist/verify.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Verification helpers used during postinstall. Two layers:
|
|
2
|
+
//
|
|
3
|
+
// 1. SHA-256 against the `checksums.txt` published by goreleaser. This
|
|
4
|
+
// is the minimum integrity check; it ensures the archive matches what
|
|
5
|
+
// the GitHub release advertised.
|
|
6
|
+
//
|
|
7
|
+
// 2. Cosign keyless signature on `checksums.txt.sig` / `checksums.txt.pem`,
|
|
8
|
+
// when the `cosign` binary is on PATH. This is the strongest tier:
|
|
9
|
+
// proves the checksums file was produced by the
|
|
10
|
+
// secretgenerator GitHub Actions workflow (Sigstore Fulcio + GitHub
|
|
11
|
+
// OIDC). When cosign is not present we still trust the SHA-256 because
|
|
12
|
+
// the file came from the same HTTPS GitHub host that signed it; the
|
|
13
|
+
// cosign step is a defense-in-depth, not the primary chain.
|
|
14
|
+
//
|
|
15
|
+
// We deliberately do NOT bundle a cosign binary in the npm package; we
|
|
16
|
+
// fall through gracefully so machines without cosign still get the
|
|
17
|
+
// installer to work.
|
|
18
|
+
import { createHash } from "node:crypto";
|
|
19
|
+
import { spawnSync } from "node:child_process";
|
|
20
|
+
import { readFileSync } from "node:fs";
|
|
21
|
+
export class IntegrityError extends Error {
|
|
22
|
+
}
|
|
23
|
+
/** Returns lowercase-hex SHA-256 of a file. */
|
|
24
|
+
export function sha256OfFile(p) {
|
|
25
|
+
const h = createHash("sha256");
|
|
26
|
+
h.update(readFileSync(p));
|
|
27
|
+
return h.digest("hex");
|
|
28
|
+
}
|
|
29
|
+
/** Parses the goreleaser-style checksums.txt:
|
|
30
|
+
*
|
|
31
|
+
* abc...123 secretgenerator_v2.0.0_linux_amd64.tar.gz
|
|
32
|
+
*
|
|
33
|
+
* Returns a map from filename to lowercase-hex SHA-256. Lines that do not
|
|
34
|
+
* match the shape are silently skipped (the file may contain blank lines
|
|
35
|
+
* or future headers).
|
|
36
|
+
*/
|
|
37
|
+
export function parseChecksums(text) {
|
|
38
|
+
const m = new Map();
|
|
39
|
+
for (const line of text.split(/\r?\n/)) {
|
|
40
|
+
const match = line.match(/^([0-9a-f]{64})\s+\*?(.+?)\s*$/i);
|
|
41
|
+
if (match) {
|
|
42
|
+
m.set(match[2], match[1].toLowerCase());
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return m;
|
|
46
|
+
}
|
|
47
|
+
/** Throws IntegrityError when the SHA-256 of `archivePath` does not
|
|
48
|
+
* match the entry for `archiveName` in `checksums.txt`. */
|
|
49
|
+
export function verifyChecksum(archivePath, archiveName, checksumsText) {
|
|
50
|
+
const map = parseChecksums(checksumsText);
|
|
51
|
+
const expected = map.get(archiveName);
|
|
52
|
+
if (!expected) {
|
|
53
|
+
throw new IntegrityError(`checksums.txt has no entry for ${archiveName}. ` +
|
|
54
|
+
"Was the release truncated, or is this an unexpected version tag?");
|
|
55
|
+
}
|
|
56
|
+
const got = sha256OfFile(archivePath);
|
|
57
|
+
if (got !== expected) {
|
|
58
|
+
throw new IntegrityError(`SHA-256 mismatch for ${archiveName}: got ${got}, want ${expected}. ` +
|
|
59
|
+
"The archive was modified in transit. Aborting installation.");
|
|
60
|
+
}
|
|
61
|
+
return expected;
|
|
62
|
+
}
|
|
63
|
+
/** Returns true when `cosign` is on PATH. Used to gate the keyless
|
|
64
|
+
* signature verification step (best-effort, optional). */
|
|
65
|
+
export function cosignAvailable() {
|
|
66
|
+
const r = spawnSync("cosign", ["version"], { stdio: "ignore" });
|
|
67
|
+
return r.status === 0;
|
|
68
|
+
}
|
|
69
|
+
/** Verifies cosign keyless signature on checksums.txt. The certificate
|
|
70
|
+
* identity is constrained to the secretgenerator release workflow; only
|
|
71
|
+
* files signed by that identity pass. Returns true on success, false
|
|
72
|
+
* (with a console.warn) on any failure — failure is non-fatal because
|
|
73
|
+
* the SHA-256 chain already authenticated the archive. */
|
|
74
|
+
export function verifyCosign(checksumsPath, certPath, sigPath) {
|
|
75
|
+
const args = [
|
|
76
|
+
"verify-blob",
|
|
77
|
+
"--certificate",
|
|
78
|
+
certPath,
|
|
79
|
+
"--signature",
|
|
80
|
+
sigPath,
|
|
81
|
+
"--certificate-identity-regexp",
|
|
82
|
+
"https://github.com/rafaelperoco/secretgenerator/.github/workflows/release.yml@refs/tags/v.*",
|
|
83
|
+
"--certificate-oidc-issuer",
|
|
84
|
+
"https://token.actions.githubusercontent.com",
|
|
85
|
+
checksumsPath,
|
|
86
|
+
];
|
|
87
|
+
const r = spawnSync("cosign", args, { encoding: "utf8" });
|
|
88
|
+
if (r.status !== 0) {
|
|
89
|
+
console.warn(`[secretgenerator] cosign verification failed (non-fatal): ${(r.stderr || "").trim()}`);
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@secretgenerator/cli",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Zero-config installer for the secretgenerator CLI. Downloads the right binary for your OS/arch from a verified GitHub release, checks the SHA-256, and (when cosign is available) verifies the keyless Sigstore signature.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://secretgenerator.org",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/rafaelperoco/secretgenerator.git",
|
|
11
|
+
"directory": "cli"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"secretgenerator",
|
|
15
|
+
"secret-generation",
|
|
16
|
+
"password-generator",
|
|
17
|
+
"csprng",
|
|
18
|
+
"cli",
|
|
19
|
+
"auditable",
|
|
20
|
+
"sigstore",
|
|
21
|
+
"slsa",
|
|
22
|
+
"cosign"
|
|
23
|
+
],
|
|
24
|
+
"bin": {
|
|
25
|
+
"secretgenerator": "dist/run.js"
|
|
26
|
+
},
|
|
27
|
+
"main": "dist/run.js",
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md"
|
|
31
|
+
],
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsc -p tsconfig.json && chmod +x dist/run.js",
|
|
34
|
+
"prepack": "npm run build",
|
|
35
|
+
"postinstall": "node dist/install.js || echo 'secretgenerator: postinstall skipped (likely a tarball-only environment); run `npx secretgenerator --help` to retry'"
|
|
36
|
+
},
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=22.12.0"
|
|
39
|
+
},
|
|
40
|
+
"os": [
|
|
41
|
+
"linux",
|
|
42
|
+
"darwin",
|
|
43
|
+
"win32"
|
|
44
|
+
],
|
|
45
|
+
"cpu": [
|
|
46
|
+
"x64",
|
|
47
|
+
"arm64"
|
|
48
|
+
],
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^22.10.0",
|
|
51
|
+
"typescript": "^5.6.0"
|
|
52
|
+
}
|
|
53
|
+
}
|