gcb-client 0.7.1 → 0.8.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 +16 -2
- package/bin/gcb.js +6 -6
- package/lib/commands/gh.d.ts +3 -3
- package/lib/commands/gh.d.ts.map +1 -1
- package/lib/commands/gh.js +95 -47
- package/lib/commands/gh.js.map +1 -1
- package/lib/commands/host-submit.d.ts +8 -8
- package/lib/commands/host-submit.d.ts.map +1 -1
- package/lib/commands/host-submit.js +32 -22
- package/lib/commands/host-submit.js.map +1 -1
- package/lib/commands/logs.d.ts +2 -2
- package/lib/commands/logs.d.ts.map +1 -1
- package/lib/commands/logs.js +17 -11
- package/lib/commands/logs.js.map +1 -1
- package/lib/commands/pr.d.ts +2 -2
- package/lib/commands/pr.d.ts.map +1 -1
- package/lib/commands/pr.js +186 -69
- package/lib/commands/pr.js.map +1 -1
- package/lib/commands/probe.d.ts +2 -2
- package/lib/commands/probe.d.ts.map +1 -1
- package/lib/commands/probe.js +19 -13
- package/lib/commands/probe.js.map +1 -1
- package/lib/commands/remotes.d.ts +24 -21
- package/lib/commands/remotes.d.ts.map +1 -1
- package/lib/commands/remotes.js +71 -53
- package/lib/commands/remotes.js.map +1 -1
- package/lib/commands/repo.d.ts.map +1 -1
- package/lib/commands/repo.js +26 -16
- package/lib/commands/repo.js.map +1 -1
- package/lib/commands/setup.d.ts +7 -7
- package/lib/commands/setup.d.ts.map +1 -1
- package/lib/commands/setup.js +38 -27
- package/lib/commands/setup.js.map +1 -1
- package/lib/helper.d.ts +27 -27
- package/lib/helper.d.ts.map +1 -1
- package/lib/helper.js +82 -66
- package/lib/helper.js.map +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +13 -8
- package/lib/index.js.map +1 -1
- package/lib/primary.d.ts +5 -5
- package/lib/primary.d.ts.map +1 -1
- package/lib/primary.js +5 -5
- package/lib/primary.js.map +1 -1
- package/package.json +10 -10
package/lib/commands/repo.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repo.js","sourceRoot":"","sources":["../../src/commands/repo.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"repo.js","sourceRoot":"","sources":["../../src/commands/repo.ts"],"names":[],"mappings":"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"}
|
package/lib/commands/setup.d.ts
CHANGED
|
@@ -34,9 +34,9 @@ export interface SetupResult {
|
|
|
34
34
|
/**
|
|
35
35
|
* Apply the configuration.
|
|
36
36
|
*
|
|
37
|
-
* @param input -
|
|
38
|
-
* @returns
|
|
39
|
-
* @throws {Error}
|
|
37
|
+
* @param input - The resolved options.
|
|
38
|
+
* @returns What was done.
|
|
39
|
+
* @throws {Error} When the target config is a symlink, or inside a directory the container shares.
|
|
40
40
|
*/
|
|
41
41
|
export declare function performSetup(input: SetupInput): Promise<SetupResult>;
|
|
42
42
|
/** Usage text for `setup`. */
|
|
@@ -44,15 +44,15 @@ export declare const SETUP_USAGE = "Usage: gcb setup [options]\n\nConfigure this
|
|
|
44
44
|
/**
|
|
45
45
|
* Run the `setup` command.
|
|
46
46
|
*
|
|
47
|
-
* @param argv -
|
|
48
|
-
* @returns
|
|
47
|
+
* @param argv - Arguments after the command name.
|
|
48
|
+
* @returns The process exit code.
|
|
49
49
|
*/
|
|
50
50
|
export declare function runSetup(argv: readonly string[]): Promise<number>;
|
|
51
51
|
/**
|
|
52
52
|
* Collect the repeatable `--allow` flag; exported so `init` and tests share one implementation.
|
|
53
53
|
*
|
|
54
|
-
* @param args -
|
|
55
|
-
* @returns
|
|
54
|
+
* @param args - The parsed arguments.
|
|
55
|
+
* @returns The entries.
|
|
56
56
|
*/
|
|
57
57
|
export declare function allowList(args: ReturnType<typeof parseArgs>): string[];
|
|
58
58
|
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAsBA,OAAO,EAQL,SAAS,EAKV,MAAM,UAAU,CAAA;AAEjB,0CAA0C;AAC1C,MAAM,WAAW,UAAU;IACzB,wFAAwF;IACxF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,uCAAuC;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,gCAAgC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,yFAAyF;IACzF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,qFAAqF;IACrF,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IACtC,yDAAyD;IACzD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,wFAAwF;IACxF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACpC;AAED,wBAAwB;AACxB,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAgG1E;AAED,8BAA8B;AAC9B,eAAO,MAAM,WAAW,m3BAcvB,CAAA;AAED;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAoDvE;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,GAAG,MAAM,EAAE,CAEtE"}
|
package/lib/commands/setup.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `setup` — configure the git in
|
|
2
|
+
* `setup` — configure the git in _this_ environment to use the broker.
|
|
3
3
|
*
|
|
4
|
-
* This is the container-side half, and it replaces the old `container-setup.sh`. It is written
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* This is the container-side half, and it replaces the old `container-setup.sh`. It is written to a
|
|
5
|
+
* git config that belongs to the running user, never to a shared repository or to the host's own
|
|
6
|
+
* configuration.
|
|
7
7
|
*
|
|
8
8
|
* It does four things, each for a reason that was measured rather than assumed:
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
9
|
+
*
|
|
10
|
+
* - Points `credential.helper` at the installed helper and turns on `credential.useHttpPath`, without
|
|
11
|
+
* which git sends no repository path and the broker can only authorize host-wide;
|
|
12
|
+
* - Rewrites the ssh remote to https _in this environment only_, because an App installation token
|
|
13
|
+
* cannot be used over ssh and this container has no ssh key at all;
|
|
14
|
+
* - Supplies a CA bundle when the image has none, because git then cannot verify any TLS certificate
|
|
15
|
+
* while Node still can — a pair of symptoms that looks like an application bug;
|
|
16
|
+
* - Records the socket path in a file as well as in the environment, because git is often spawned
|
|
17
|
+
* from a non-login shell that never sources a profile.
|
|
17
18
|
*/
|
|
18
19
|
import fs from 'node:fs';
|
|
19
20
|
import os from 'node:os';
|
|
@@ -22,9 +23,9 @@ import { fail, findSystemCaBundle, gitConfigList, gitConfigSet, insideMountedPat
|
|
|
22
23
|
/**
|
|
23
24
|
* Apply the configuration.
|
|
24
25
|
*
|
|
25
|
-
* @param input -
|
|
26
|
-
* @returns
|
|
27
|
-
* @throws {Error}
|
|
26
|
+
* @param input - The resolved options.
|
|
27
|
+
* @returns What was done.
|
|
28
|
+
* @throws {Error} When the target config is a symlink, or inside a directory the container shares.
|
|
28
29
|
*/
|
|
29
30
|
export async function performSetup(input) {
|
|
30
31
|
// Writing through a symlink would edit whatever it points at, and a config that lives in a directory
|
|
@@ -52,7 +53,9 @@ export async function performSetup(input) {
|
|
|
52
53
|
entries: [
|
|
53
54
|
`credential.helper=${input.helper}`,
|
|
54
55
|
'credential.useHttpPath=true',
|
|
55
|
-
...(input.rewriteSshHost
|
|
56
|
+
...(input.rewriteSshHost
|
|
57
|
+
? [`url.https://${input.rewriteSshHost}/.insteadOf=git@${input.rewriteSshHost}:`]
|
|
58
|
+
: []),
|
|
56
59
|
],
|
|
57
60
|
caBundle: findSystemCaBundle() ? null : input.caBundlePath,
|
|
58
61
|
socketFile: input.socketFile,
|
|
@@ -121,8 +124,8 @@ Configure this environment's git to obtain credentials from the broker.
|
|
|
121
124
|
/**
|
|
122
125
|
* Run the `setup` command.
|
|
123
126
|
*
|
|
124
|
-
* @param argv -
|
|
125
|
-
* @returns
|
|
127
|
+
* @param argv - Arguments after the command name.
|
|
128
|
+
* @returns The process exit code.
|
|
126
129
|
*/
|
|
127
130
|
export async function runSetup(argv) {
|
|
128
131
|
const args = parseArgs(argv, { booleans: ['no-rewrite-ssh', 'dry-run', 'help'] });
|
|
@@ -142,24 +145,32 @@ export async function runSetup(argv) {
|
|
|
142
145
|
gitconfig: args.value('gitconfig') ?? path.join(home, '.gitconfig'),
|
|
143
146
|
envFile: args.value('env-file') ?? path.join(home, '.git-broker.env'),
|
|
144
147
|
socketFile: args.value('socket-file') ?? path.join(home, '.config', 'git-credential-broker', 'socket'),
|
|
145
|
-
caBundlePath: args.value('ca-bundle') ??
|
|
146
|
-
|
|
148
|
+
caBundlePath: args.value('ca-bundle') ??
|
|
149
|
+
path.join(home, '.config', 'git-credential-broker', 'ca-bundle.pem'),
|
|
150
|
+
rewriteSshHost: args.has('no-rewrite-ssh')
|
|
151
|
+
? null
|
|
152
|
+
: (args.value('rewrite-ssh') ?? 'github.com'),
|
|
147
153
|
dryRun: args.has('dry-run'),
|
|
148
154
|
home,
|
|
149
155
|
});
|
|
150
156
|
say(`git config : ${result.gitconfig}${args.has('dry-run') ? ' (dry run)' : ''}`);
|
|
151
|
-
for (const entry of result.entries)
|
|
157
|
+
for (const entry of result.entries) {
|
|
152
158
|
say(` ${entry}`);
|
|
153
|
-
|
|
159
|
+
}
|
|
160
|
+
if (result.caBundle) {
|
|
154
161
|
say(`CA bundle : ${result.caBundle}`);
|
|
162
|
+
}
|
|
155
163
|
say(`socket file : ${result.socketFile}`);
|
|
156
164
|
say(`env file : ${result.envFile}`);
|
|
157
|
-
for (const warning of result.warnings)
|
|
165
|
+
for (const warning of result.warnings) {
|
|
158
166
|
warn(`warning: ${warning}`);
|
|
159
|
-
|
|
167
|
+
}
|
|
168
|
+
if (args.has('dry-run')) {
|
|
160
169
|
say('dry run: nothing was written');
|
|
161
|
-
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
162
172
|
say('\nnext: start the broker (gcb daemon) and verify with `gcb probe`.');
|
|
173
|
+
}
|
|
163
174
|
return 0;
|
|
164
175
|
}
|
|
165
176
|
catch (error) {
|
|
@@ -169,8 +180,8 @@ export async function runSetup(argv) {
|
|
|
169
180
|
/**
|
|
170
181
|
* Collect the repeatable `--allow` flag; exported so `init` and tests share one implementation.
|
|
171
182
|
*
|
|
172
|
-
* @param args -
|
|
173
|
-
* @returns
|
|
183
|
+
* @param args - The parsed arguments.
|
|
184
|
+
* @returns The entries.
|
|
174
185
|
*/
|
|
175
186
|
export function allowList(args) {
|
|
176
187
|
return listFlag(args, 'allow');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"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"}
|
package/lib/helper.d.ts
CHANGED
|
@@ -16,62 +16,62 @@ export interface HelperArgs {
|
|
|
16
16
|
/**
|
|
17
17
|
* Parse git's credential description.
|
|
18
18
|
*
|
|
19
|
-
* @param text -
|
|
20
|
-
* @returns
|
|
19
|
+
* @param text - The raw stdin contents.
|
|
20
|
+
* @returns The key/value pairs.
|
|
21
21
|
*/
|
|
22
22
|
export declare function parseCredentialInput(text: string): Record<string, string>;
|
|
23
23
|
/**
|
|
24
24
|
* Read a stream to the end, with a size ceiling.
|
|
25
25
|
*
|
|
26
|
-
* Chunks are normalized to `Buffer` rather than assumed: `process.stdin` yields buffers, but
|
|
27
|
-
*
|
|
26
|
+
* Chunks are normalized to `Buffer` rather than assumed: `process.stdin` yields buffers, but any
|
|
27
|
+
* stream in string or object mode yields strings, and `Buffer.concat` rejects those.
|
|
28
28
|
*
|
|
29
|
-
* @param stream -
|
|
30
|
-
* @param maxBytes -
|
|
31
|
-
* @returns
|
|
29
|
+
* @param stream - The stream to drain.
|
|
30
|
+
* @param maxBytes - Ceiling; exceeding it rejects.
|
|
31
|
+
* @returns The decoded contents.
|
|
32
32
|
*/
|
|
33
33
|
export declare function readAll(stream: Readable, maxBytes?: number): Promise<string>;
|
|
34
34
|
/**
|
|
35
35
|
* Send one request to the broker over its unix socket and await one response.
|
|
36
36
|
*
|
|
37
|
-
* @param socketPath -
|
|
38
|
-
* @param request -
|
|
39
|
-
* @param timeoutMs -
|
|
40
|
-
* @returns
|
|
37
|
+
* @param socketPath - The broker socket path.
|
|
38
|
+
* @param request - The request payload.
|
|
39
|
+
* @param timeoutMs - How long to wait for an answer.
|
|
40
|
+
* @returns The parsed response.
|
|
41
41
|
*/
|
|
42
42
|
export declare function requestOverSocket(socketPath: string, request: Record<string, unknown>, timeoutMs?: number): Promise<WireResponse>;
|
|
43
43
|
/**
|
|
44
44
|
* Decide where the broker lives, in precedence order:
|
|
45
45
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
46
|
+
* 1. `--socket <path>` on the command line;
|
|
47
|
+
* 2. `GIT_BROKER_SOCKET`;
|
|
48
|
+
* 3. The contents of `GIT_BROKER_SOCKET_FILE`, defaulting to
|
|
49
|
+
* `$HOME/.config/git-credential-broker/socket`.
|
|
50
50
|
*
|
|
51
|
-
* An empty or missing result means "not configured in this environment", which the caller
|
|
52
|
-
*
|
|
51
|
+
* An empty or missing result means "not configured in this environment", which the caller treats as
|
|
52
|
+
* "behave as if not installed".
|
|
53
53
|
*
|
|
54
|
-
* @param explicitSocket -
|
|
55
|
-
* @param env -
|
|
56
|
-
* @returns
|
|
54
|
+
* @param explicitSocket - The `--socket` argument, if any.
|
|
55
|
+
* @param env - The environment to read.
|
|
56
|
+
* @returns The resolved socket path, or undefined when nothing is configured.
|
|
57
57
|
*/
|
|
58
58
|
export declare function resolveSocketPath(explicitSocket: string | undefined, env: NodeJS.ProcessEnv): string | undefined;
|
|
59
59
|
/**
|
|
60
60
|
* Parse the helper's own command line.
|
|
61
61
|
*
|
|
62
|
-
* @param argv -
|
|
63
|
-
* @returns
|
|
62
|
+
* @param argv - Arguments after the script name.
|
|
63
|
+
* @returns The parsed arguments.
|
|
64
64
|
*/
|
|
65
65
|
export declare function parseArgs(argv: readonly string[]): HelperArgs;
|
|
66
66
|
/**
|
|
67
67
|
* Run the helper.
|
|
68
68
|
*
|
|
69
|
-
* Always resolves with an exit code; refusals still exit 0 on purpose (see the module
|
|
70
|
-
*
|
|
69
|
+
* Always resolves with an exit code; refusals still exit 0 on purpose (see the module comment) so
|
|
70
|
+
* that git stops instead of falling through to another helper.
|
|
71
71
|
*
|
|
72
|
-
* @param argv -
|
|
73
|
-
* @param io -
|
|
74
|
-
* @returns
|
|
72
|
+
* @param argv - Arguments after the script name.
|
|
73
|
+
* @param io - Injectable streams and environment.
|
|
74
|
+
* @returns The process exit code.
|
|
75
75
|
*/
|
|
76
76
|
export declare function runHelper(argv: readonly string[], io?: HelperIO): Promise<number>;
|
|
77
77
|
//# sourceMappingURL=helper.d.ts.map
|
package/lib/helper.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAIrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAiB5C,qDAAqD;AACrD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAA;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAA;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAA;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CACjC;AAED,wCAAwC;AACxC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAazE;AAED;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAE,MAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB7F;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,SAAS,GAAE,MAA0B,GACpC,OAAO,CAAC,YAAY,CAAC,CAiDvB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,MAAM,GAAG,SAAS,CAoBpB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAyB7D;AAED;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,EAAE,GAAE,QAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAsG3F"}
|
package/lib/helper.js
CHANGED
|
@@ -1,38 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The container side: a git credential helper.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Git invokes this as `gcb <get|store|erase>` with a small `key=value` description on stdin, and
|
|
5
|
+
* reads `key=value` pairs back from stdout.
|
|
6
6
|
*
|
|
7
7
|
* What it deliberately does:
|
|
8
|
-
* - `store` and `erase` do nothing, ever, so no credential is written to
|
|
9
|
-
* `~/.git-credentials` or anywhere else;
|
|
10
|
-
* - it refuses a request without a `path`, because a path-less request can only be
|
|
11
|
-
* authorized at host granularity — exactly the over-grant this design exists to prevent;
|
|
12
|
-
* - on any refusal it emits `quit=1` and exits 0. That is the git credential protocol's way
|
|
13
|
-
* of saying "stop asking helpers": an exit code alone would let git fall through to
|
|
14
|
-
* another helper and silently authenticate as someone else;
|
|
15
|
-
* - it never prints the credential to stderr, and never prints diagnostics to stdout, where
|
|
16
|
-
* they would corrupt the protocol;
|
|
17
|
-
* - it forwards the protocol and lets the *broker* decide whether plaintext is acceptable
|
|
18
|
-
* for that host. That decision is therefore host-side and cannot be widened from inside the
|
|
19
|
-
* container; the helper only rejects a protocol it cannot reason about at all.
|
|
20
8
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
9
|
+
* - `store` and `erase` do nothing, ever, so no credential is written to `~/.git-credentials` or
|
|
10
|
+
* anywhere else;
|
|
11
|
+
* - It refuses a request without a `path`, because a path-less request can only be authorized at host
|
|
12
|
+
* granularity — exactly the over-grant this design exists to prevent;
|
|
13
|
+
* - On any refusal it emits `quit=1` and exits 0. That is the git credential protocol's way of saying
|
|
14
|
+
* "stop asking helpers": an exit code alone would let git fall through to another helper and
|
|
15
|
+
* silently authenticate as someone else;
|
|
16
|
+
* - It never prints the credential to stderr, and never prints diagnostics to stdout, where they
|
|
17
|
+
* would corrupt the protocol;
|
|
18
|
+
* - It forwards the protocol and lets the _broker_ decide whether plaintext is acceptable for that
|
|
19
|
+
* host. That decision is therefore host-side and cannot be widened from inside the container; the
|
|
20
|
+
* helper only rejects a protocol it cannot reason about at all.
|
|
21
|
+
*
|
|
22
|
+
* One exception to fail-closed, and it matters because the workspace is a bind mount shared with
|
|
23
|
+
* the host: when no broker is configured at all (`GIT_BROKER_SOCKET` unset), the helper behaves as
|
|
24
|
+
* if it were not installed — no output, exit 0 — so the human's own git keeps its own credential
|
|
25
|
+
* chain for https remotes. It refuses with `quit=1` only when it _is_ configured (socket set, or
|
|
26
|
+
* `GIT_BROKER_REQUIRE=1`), because that means we are meant to be the authority. Set
|
|
27
|
+
* `GIT_BROKER_REQUIRE=1` in the container so a missing socket variable can never degrade into
|
|
28
|
+
* "silently rely on something else".
|
|
28
29
|
*
|
|
29
30
|
* The helper is stateless: it holds no secret and knows no allowlist. The broker decides.
|
|
30
31
|
*/
|
|
31
32
|
import { readFileSync } from 'node:fs';
|
|
32
33
|
import net from 'node:net';
|
|
33
|
-
import { StringDecoder } from 'node:string_decoder';
|
|
34
34
|
import { homedir } from 'node:os';
|
|
35
35
|
import path from 'node:path';
|
|
36
|
+
import { StringDecoder } from 'node:string_decoder';
|
|
36
37
|
import { asWireResponse, encodeMessage, parseMessage } from 'gcb-core';
|
|
37
38
|
/** Ceiling for the description git sends us. */
|
|
38
39
|
const MAX_INPUT_BYTES = 8 * 1024;
|
|
@@ -41,25 +42,27 @@ const SOCKET_TIMEOUT_MS = 10_000;
|
|
|
41
42
|
/**
|
|
42
43
|
* Where to look for the socket path when no environment variable is set.
|
|
43
44
|
*
|
|
44
|
-
* A file rather than only an environment variable, because git is often spawned from a
|
|
45
|
-
*
|
|
46
|
-
*
|
|
45
|
+
* A file rather than only an environment variable, because git is often spawned from a non-login
|
|
46
|
+
* shell that never sources a profile: relying on the environment alone means pushes mysteriously
|
|
47
|
+
* stop working in a fresh session. Override with `GIT_BROKER_SOCKET_FILE`.
|
|
47
48
|
*/
|
|
48
49
|
const DEFAULT_SOCKET_FILE = ['.config', 'git-credential-broker', 'socket'];
|
|
49
50
|
/**
|
|
50
51
|
* Parse git's credential description.
|
|
51
52
|
*
|
|
52
|
-
* @param text -
|
|
53
|
-
* @returns
|
|
53
|
+
* @param text - The raw stdin contents.
|
|
54
|
+
* @returns The key/value pairs.
|
|
54
55
|
*/
|
|
55
56
|
export function parseCredentialInput(text) {
|
|
56
57
|
const fields = {};
|
|
57
58
|
for (const line of String(text).split('\n')) {
|
|
58
|
-
if (!line)
|
|
59
|
+
if (!line) {
|
|
59
60
|
continue;
|
|
61
|
+
}
|
|
60
62
|
const separator = line.indexOf('=');
|
|
61
|
-
if (separator <= 0)
|
|
63
|
+
if (separator <= 0) {
|
|
62
64
|
continue;
|
|
65
|
+
}
|
|
63
66
|
fields[line.slice(0, separator).trim()] = line.slice(separator + 1);
|
|
64
67
|
}
|
|
65
68
|
return fields;
|
|
@@ -67,12 +70,12 @@ export function parseCredentialInput(text) {
|
|
|
67
70
|
/**
|
|
68
71
|
* Read a stream to the end, with a size ceiling.
|
|
69
72
|
*
|
|
70
|
-
* Chunks are normalized to `Buffer` rather than assumed: `process.stdin` yields buffers, but
|
|
71
|
-
*
|
|
73
|
+
* Chunks are normalized to `Buffer` rather than assumed: `process.stdin` yields buffers, but any
|
|
74
|
+
* stream in string or object mode yields strings, and `Buffer.concat` rejects those.
|
|
72
75
|
*
|
|
73
|
-
* @param stream -
|
|
74
|
-
* @param maxBytes -
|
|
75
|
-
* @returns
|
|
76
|
+
* @param stream - The stream to drain.
|
|
77
|
+
* @param maxBytes - Ceiling; exceeding it rejects.
|
|
78
|
+
* @returns The decoded contents.
|
|
76
79
|
*/
|
|
77
80
|
export function readAll(stream, maxBytes = MAX_INPUT_BYTES) {
|
|
78
81
|
return new Promise((resolve, reject) => {
|
|
@@ -95,10 +98,10 @@ export function readAll(stream, maxBytes = MAX_INPUT_BYTES) {
|
|
|
95
98
|
/**
|
|
96
99
|
* Send one request to the broker over its unix socket and await one response.
|
|
97
100
|
*
|
|
98
|
-
* @param socketPath -
|
|
99
|
-
* @param request -
|
|
100
|
-
* @param timeoutMs -
|
|
101
|
-
* @returns
|
|
101
|
+
* @param socketPath - The broker socket path.
|
|
102
|
+
* @param request - The request payload.
|
|
103
|
+
* @param timeoutMs - How long to wait for an answer.
|
|
104
|
+
* @returns The parsed response.
|
|
102
105
|
*/
|
|
103
106
|
export function requestOverSocket(socketPath, request, timeoutMs = SOCKET_TIMEOUT_MS) {
|
|
104
107
|
return new Promise((resolve, reject) => {
|
|
@@ -107,8 +110,9 @@ export function requestOverSocket(socketPath, request, timeoutMs = SOCKET_TIMEOU
|
|
|
107
110
|
let buffer = '';
|
|
108
111
|
let settled = false;
|
|
109
112
|
const settle = (callback, argument) => {
|
|
110
|
-
if (settled)
|
|
113
|
+
if (settled) {
|
|
111
114
|
return;
|
|
115
|
+
}
|
|
112
116
|
settled = true;
|
|
113
117
|
socket.destroy();
|
|
114
118
|
callback(argument);
|
|
@@ -120,13 +124,16 @@ export function requestOverSocket(socketPath, request, timeoutMs = SOCKET_TIMEOU
|
|
|
120
124
|
socket.on('data', (chunk) => {
|
|
121
125
|
buffer += decoder.write(chunk);
|
|
122
126
|
const newline = buffer.indexOf('\n');
|
|
123
|
-
if (newline < 0)
|
|
127
|
+
if (newline < 0) {
|
|
124
128
|
return;
|
|
129
|
+
}
|
|
125
130
|
const message = parseMessage(buffer.slice(0, newline));
|
|
126
|
-
if (message)
|
|
131
|
+
if (message) {
|
|
127
132
|
settle(resolve, asWireResponse(message));
|
|
128
|
-
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
129
135
|
settle(reject, new Error('the broker sent a malformed response'));
|
|
136
|
+
}
|
|
130
137
|
});
|
|
131
138
|
socket.on('error', (error) => {
|
|
132
139
|
settle(reject, new Error(`cannot reach the broker at ${socketPath}: ${error.code ?? error.message}`));
|
|
@@ -139,29 +146,32 @@ export function requestOverSocket(socketPath, request, timeoutMs = SOCKET_TIMEOU
|
|
|
139
146
|
/**
|
|
140
147
|
* Decide where the broker lives, in precedence order:
|
|
141
148
|
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
149
|
+
* 1. `--socket <path>` on the command line;
|
|
150
|
+
* 2. `GIT_BROKER_SOCKET`;
|
|
151
|
+
* 3. The contents of `GIT_BROKER_SOCKET_FILE`, defaulting to
|
|
152
|
+
* `$HOME/.config/git-credential-broker/socket`.
|
|
146
153
|
*
|
|
147
|
-
* An empty or missing result means "not configured in this environment", which the caller
|
|
148
|
-
*
|
|
154
|
+
* An empty or missing result means "not configured in this environment", which the caller treats as
|
|
155
|
+
* "behave as if not installed".
|
|
149
156
|
*
|
|
150
|
-
* @param explicitSocket -
|
|
151
|
-
* @param env -
|
|
152
|
-
* @returns
|
|
157
|
+
* @param explicitSocket - The `--socket` argument, if any.
|
|
158
|
+
* @param env - The environment to read.
|
|
159
|
+
* @returns The resolved socket path, or undefined when nothing is configured.
|
|
153
160
|
*/
|
|
154
161
|
export function resolveSocketPath(explicitSocket, env) {
|
|
155
|
-
if (explicitSocket)
|
|
162
|
+
if (explicitSocket) {
|
|
156
163
|
return explicitSocket;
|
|
164
|
+
}
|
|
157
165
|
const fromEnv = env['GIT_BROKER_SOCKET'];
|
|
158
|
-
if (fromEnv)
|
|
166
|
+
if (fromEnv) {
|
|
159
167
|
return fromEnv;
|
|
168
|
+
}
|
|
160
169
|
const file = env['GIT_BROKER_SOCKET_FILE'] ?? path.join(env['HOME'] ?? homedir(), ...DEFAULT_SOCKET_FILE);
|
|
161
170
|
try {
|
|
162
171
|
const fromFile = readFileSync(file, 'utf8').trim();
|
|
163
|
-
if (fromFile)
|
|
172
|
+
if (fromFile) {
|
|
164
173
|
return fromFile;
|
|
174
|
+
}
|
|
165
175
|
}
|
|
166
176
|
catch {
|
|
167
177
|
// No socket file: this environment is not configured for the broker.
|
|
@@ -171,8 +181,8 @@ export function resolveSocketPath(explicitSocket, env) {
|
|
|
171
181
|
/**
|
|
172
182
|
* Parse the helper's own command line.
|
|
173
183
|
*
|
|
174
|
-
* @param argv -
|
|
175
|
-
* @returns
|
|
184
|
+
* @param argv - Arguments after the script name.
|
|
185
|
+
* @returns The parsed arguments.
|
|
176
186
|
*/
|
|
177
187
|
export function parseArgs(argv) {
|
|
178
188
|
let operation = 'get';
|
|
@@ -181,8 +191,9 @@ export function parseArgs(argv) {
|
|
|
181
191
|
const rest = [];
|
|
182
192
|
for (let index = 0; index < argv.length; index += 1) {
|
|
183
193
|
const argument = argv[index];
|
|
184
|
-
if (argument === undefined)
|
|
194
|
+
if (argument === undefined) {
|
|
185
195
|
continue;
|
|
196
|
+
}
|
|
186
197
|
if (argument === '--socket') {
|
|
187
198
|
socketPath = argv[index + 1];
|
|
188
199
|
index += 1;
|
|
@@ -197,27 +208,29 @@ export function parseArgs(argv) {
|
|
|
197
208
|
rest.push(argument);
|
|
198
209
|
}
|
|
199
210
|
}
|
|
200
|
-
if (rest.length > 0)
|
|
211
|
+
if (rest.length > 0) {
|
|
201
212
|
operation = rest[0];
|
|
213
|
+
}
|
|
202
214
|
return { operation, socketPath, strict };
|
|
203
215
|
}
|
|
204
216
|
/**
|
|
205
217
|
* Run the helper.
|
|
206
218
|
*
|
|
207
|
-
* Always resolves with an exit code; refusals still exit 0 on purpose (see the module
|
|
208
|
-
*
|
|
219
|
+
* Always resolves with an exit code; refusals still exit 0 on purpose (see the module comment) so
|
|
220
|
+
* that git stops instead of falling through to another helper.
|
|
209
221
|
*
|
|
210
|
-
* @param argv -
|
|
211
|
-
* @param io -
|
|
212
|
-
* @returns
|
|
222
|
+
* @param argv - Arguments after the script name.
|
|
223
|
+
* @param io - Injectable streams and environment.
|
|
224
|
+
* @returns The process exit code.
|
|
213
225
|
*/
|
|
214
226
|
export async function runHelper(argv, io = {}) {
|
|
215
227
|
const { stdin = process.stdin, stdout = process.stdout, stderr = process.stderr, env = process.env, } = io;
|
|
216
228
|
const { operation, socketPath: socketArgument, strict: strictArgument } = parseArgs(argv);
|
|
217
229
|
// git calls `store` after a successful authentication and `erase` after a rejected one.
|
|
218
230
|
// Both are intentionally no-ops: nothing about a credential is ever persisted.
|
|
219
|
-
if (operation !== 'get')
|
|
231
|
+
if (operation !== 'get') {
|
|
220
232
|
return 0;
|
|
233
|
+
}
|
|
221
234
|
const socketPath = resolveSocketPath(socketArgument, env);
|
|
222
235
|
const strict = strictArgument || env['GIT_BROKER_REQUIRE'] === '1';
|
|
223
236
|
const refuse = (message) => {
|
|
@@ -239,8 +252,9 @@ export async function runHelper(argv, io = {}) {
|
|
|
239
252
|
// invoke this helper too. When we are not configured, act as if we were never installed:
|
|
240
253
|
// silence and exit 0 lets git move on to the next helper. Emitting `quit=1` here would stop
|
|
241
254
|
// that chain and break the host's own https credentials.
|
|
242
|
-
if (!socketPath && !strict)
|
|
255
|
+
if (!socketPath && !strict) {
|
|
243
256
|
return 0;
|
|
257
|
+
}
|
|
244
258
|
const protocol = input['protocol'];
|
|
245
259
|
if (protocol !== 'https' && protocol !== 'http') {
|
|
246
260
|
return refuse(`refusing protocol ${JSON.stringify(protocol ?? '')}: only http and https are understood`);
|
|
@@ -281,7 +295,9 @@ export async function runHelper(argv, io = {}) {
|
|
|
281
295
|
const detail = response.reason ? `: ${response.reason}` : '';
|
|
282
296
|
return refuse(`the broker refused this request (${response.code ?? 'unknown'})${detail}`);
|
|
283
297
|
}
|
|
284
|
-
if (typeof response.username !== 'string' ||
|
|
298
|
+
if (typeof response.username !== 'string' ||
|
|
299
|
+
typeof response.password !== 'string' ||
|
|
300
|
+
!response.password) {
|
|
285
301
|
return refuse('the broker returned an incomplete credential');
|
|
286
302
|
}
|
|
287
303
|
stdout.write(`username=${response.username}\npassword=${response.password}\n`);
|