@cyclonedx/cdxgen 12.3.1 → 12.3.3
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 +6 -0
- package/bin/cdxgen.js +1 -2
- package/data/rules/ai-agent-governance.yaml +43 -0
- package/data/rules/ci-permissions.yaml +132 -0
- package/data/rules/dependency-sources.yaml +65 -5
- package/data/rules/mcp-servers.yaml +36 -2
- package/data/rules/package-integrity.yaml +22 -0
- package/lib/cli/index.js +436 -56
- package/lib/cli/index.poku.js +875 -2
- package/lib/helpers/agentFormulationParser.js +10 -3
- package/lib/helpers/agentFormulationParser.poku.js +42 -0
- package/lib/helpers/aiInventory.js +262 -0
- package/lib/helpers/aiInventory.poku.js +111 -0
- package/lib/helpers/analyzer.js +413 -54
- package/lib/helpers/analyzer.poku.js +117 -0
- package/lib/helpers/auditCategories.js +76 -0
- package/lib/helpers/chromextutils.js +25 -3
- package/lib/helpers/chromextutils.poku.js +68 -0
- package/lib/helpers/ciParsers/githubActions.js +79 -0
- package/lib/helpers/ciParsers/githubActions.poku.js +103 -0
- package/lib/helpers/communityAiConfigParser.js +15 -5
- package/lib/helpers/communityAiConfigParser.poku.js +71 -0
- package/lib/helpers/depsUtils.js +5 -0
- package/lib/helpers/depsUtils.poku.js +55 -0
- package/lib/helpers/display.js +50 -24
- package/lib/helpers/display.poku.js +70 -58
- package/lib/helpers/formulationParsers.js +26 -6
- package/lib/helpers/jsonLike.js +21 -20
- package/lib/helpers/jsonLike.poku.js +34 -0
- package/lib/helpers/mcpConfigParser.js +32 -16
- package/lib/helpers/mcpConfigParser.poku.js +104 -0
- package/lib/helpers/mcpDiscovery.js +13 -23
- package/lib/helpers/mcpDiscovery.poku.js +21 -0
- package/lib/helpers/propertySanitizer.js +121 -0
- package/lib/helpers/utils.js +953 -41
- package/lib/helpers/utils.poku.js +901 -1
- package/lib/managers/binary.js +16 -0
- package/lib/managers/binary.poku.js +1 -0
- package/lib/managers/docker.js +240 -16
- package/lib/managers/docker.poku.js +1142 -2
- package/lib/server/server.js +7 -4
- package/lib/server/server.poku.js +36 -1
- package/lib/stages/postgen/annotator.js +2 -1
- package/lib/stages/postgen/annotator.poku.js +15 -0
- package/lib/stages/postgen/auditBom.js +12 -6
- package/lib/stages/postgen/auditBom.poku.js +755 -6
- package/lib/stages/postgen/postgen.js +229 -6
- package/lib/stages/postgen/postgen.poku.js +180 -0
- package/package.json +2 -1
- package/types/lib/cli/index.d.ts +1 -0
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/helpers/agentFormulationParser.d.ts +19 -0
- package/types/lib/helpers/agentFormulationParser.d.ts.map +1 -0
- package/types/lib/helpers/aiInventory.d.ts +23 -0
- package/types/lib/helpers/aiInventory.d.ts.map +1 -0
- package/types/lib/helpers/analyzer.d.ts +5 -0
- package/types/lib/helpers/analyzer.d.ts.map +1 -1
- package/types/lib/helpers/auditCategories.d.ts +12 -0
- package/types/lib/helpers/auditCategories.d.ts.map +1 -0
- package/types/lib/helpers/chromextutils.d.ts.map +1 -1
- package/types/lib/helpers/ciParsers/githubActions.d.ts.map +1 -1
- package/types/lib/helpers/communityAiConfigParser.d.ts +29 -0
- package/types/lib/helpers/communityAiConfigParser.d.ts.map +1 -0
- package/types/lib/helpers/depsUtils.d.ts.map +1 -1
- package/types/lib/helpers/display.d.ts +1 -0
- package/types/lib/helpers/display.d.ts.map +1 -1
- package/types/lib/helpers/formulationParsers.d.ts.map +1 -1
- package/types/lib/helpers/jsonLike.d.ts +4 -0
- package/types/lib/helpers/jsonLike.d.ts.map +1 -0
- package/types/lib/helpers/mcp.d.ts +29 -0
- package/types/lib/helpers/mcp.d.ts.map +1 -0
- package/types/lib/helpers/mcpConfigParser.d.ts +30 -0
- package/types/lib/helpers/mcpConfigParser.d.ts.map +1 -0
- package/types/lib/helpers/mcpDiscovery.d.ts +5 -0
- package/types/lib/helpers/mcpDiscovery.d.ts.map +1 -0
- package/types/lib/helpers/propertySanitizer.d.ts +3 -0
- package/types/lib/helpers/propertySanitizer.d.ts.map +1 -0
- package/types/lib/helpers/utils.d.ts +31 -0
- package/types/lib/helpers/utils.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts +3 -0
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/server/server.d.ts +1 -0
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
- package/types/lib/stages/postgen/auditBom.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
package/lib/managers/binary.js
CHANGED
|
@@ -16,11 +16,13 @@ import { createContainerRiskProperties } from "../helpers/containerRisk.js";
|
|
|
16
16
|
import { createGtfoBinsProperties } from "../helpers/gtfobins.js";
|
|
17
17
|
import {
|
|
18
18
|
adjustLicenseInformation,
|
|
19
|
+
attachIdentityTools,
|
|
19
20
|
collectExecutables,
|
|
20
21
|
collectSharedLibs,
|
|
21
22
|
DEBUG_MODE,
|
|
22
23
|
dirNameStr,
|
|
23
24
|
extractPathEnv,
|
|
25
|
+
extractToolRefs,
|
|
24
26
|
findLicenseId,
|
|
25
27
|
getTmpDir,
|
|
26
28
|
isDryRun,
|
|
@@ -465,6 +467,7 @@ export async function getOSPackages(src, imageConfig) {
|
|
|
465
467
|
executables: [],
|
|
466
468
|
osPackages: [],
|
|
467
469
|
sharedLibs: [],
|
|
470
|
+
tools: [],
|
|
468
471
|
};
|
|
469
472
|
}
|
|
470
473
|
const pkgList = [];
|
|
@@ -472,6 +475,7 @@ export async function getOSPackages(src, imageConfig) {
|
|
|
472
475
|
const allTypes = new Set();
|
|
473
476
|
const bundledSdks = new Set();
|
|
474
477
|
const bundledRuntimes = new Set();
|
|
478
|
+
let tools = [];
|
|
475
479
|
let binPaths = extractPathEnv(imageConfig?.Env);
|
|
476
480
|
if (!binPaths?.length) {
|
|
477
481
|
const rootBinPaths = getDirs(src, "{sbin,bin}", true, false);
|
|
@@ -633,6 +637,15 @@ export async function getOSPackages(src, imageConfig) {
|
|
|
633
637
|
}
|
|
634
638
|
}
|
|
635
639
|
const tmpDependencies = {};
|
|
640
|
+
const toolRefs = extractToolRefs(
|
|
641
|
+
tmpBom?.metadata?.tools,
|
|
642
|
+
(tool) => tool?.name !== "cdxgen",
|
|
643
|
+
);
|
|
644
|
+
tools = (
|
|
645
|
+
Array.isArray(tmpBom?.metadata?.tools)
|
|
646
|
+
? tmpBom.metadata.tools
|
|
647
|
+
: tmpBom?.metadata?.tools?.components || []
|
|
648
|
+
).filter((tool) => tool?.["bom-ref"] && tool?.name !== "cdxgen");
|
|
636
649
|
(tmpBom.dependencies || []).forEach((d) => {
|
|
637
650
|
tmpDependencies[d.ref] = d.dependsOn;
|
|
638
651
|
});
|
|
@@ -781,6 +794,7 @@ export async function getOSPackages(src, imageConfig) {
|
|
|
781
794
|
console.log(err);
|
|
782
795
|
}
|
|
783
796
|
}
|
|
797
|
+
attachIdentityTools(comp, toolRefs);
|
|
784
798
|
// Fix licenses
|
|
785
799
|
if (
|
|
786
800
|
comp.licenses &&
|
|
@@ -916,6 +930,7 @@ export async function getOSPackages(src, imageConfig) {
|
|
|
916
930
|
).toString();
|
|
917
931
|
}
|
|
918
932
|
newComp["bom-ref"] = decodeURIComponent(newComp.purl);
|
|
933
|
+
attachIdentityTools(newComp, toolRefs);
|
|
919
934
|
pkgList.push(newComp);
|
|
920
935
|
detectSdksRuntimes(newComp, bundledSdks, bundledRuntimes);
|
|
921
936
|
}
|
|
@@ -968,6 +983,7 @@ export async function getOSPackages(src, imageConfig) {
|
|
|
968
983
|
binPaths,
|
|
969
984
|
executables,
|
|
970
985
|
sharedLibs,
|
|
986
|
+
tools,
|
|
971
987
|
};
|
|
972
988
|
}
|
|
973
989
|
|
|
@@ -60,6 +60,7 @@ it("getOSPackages() returns empty collections and reports a blocked dry-run acti
|
|
|
60
60
|
assert.deepStrictEqual(result.dependenciesList, []);
|
|
61
61
|
assert.deepStrictEqual(result.binPaths, []);
|
|
62
62
|
assert.deepStrictEqual(Array.from(result.allTypes), []);
|
|
63
|
+
assert.deepStrictEqual(result.tools, []);
|
|
63
64
|
sinon.assert.calledWithMatch(recordActivity, {
|
|
64
65
|
kind: "container",
|
|
65
66
|
status: "blocked",
|
package/lib/managers/docker.js
CHANGED
|
@@ -32,6 +32,13 @@ import { getDirs, getOnlyDirs } from "./containerutils.js";
|
|
|
32
32
|
|
|
33
33
|
export const isWin = _platform() === "win32";
|
|
34
34
|
export const DOCKER_HUB_REGISTRY = "docker.io";
|
|
35
|
+
// Docker commonly stores Hub credentials under index.docker.io or
|
|
36
|
+
// registry-1.docker.io while pulls target docker.io.
|
|
37
|
+
const DOCKER_HUB_REGISTRY_ALIASES = new Set([
|
|
38
|
+
DOCKER_HUB_REGISTRY,
|
|
39
|
+
"index.docker.io",
|
|
40
|
+
"registry-1.docker.io",
|
|
41
|
+
]);
|
|
35
42
|
|
|
36
43
|
/**
|
|
37
44
|
* Encode a value as base64url (RFC 4648 §5) with padding.
|
|
@@ -42,6 +49,212 @@ export const DOCKER_HUB_REGISTRY = "docker.io";
|
|
|
42
49
|
const toBase64Url = (value) =>
|
|
43
50
|
Buffer.from(value).toString("base64").replace(/\+/g, "-").replace(/\//g, "_");
|
|
44
51
|
|
|
52
|
+
const normalizeRegistryPath = (registryPath) => {
|
|
53
|
+
if (!registryPath || registryPath === "/") {
|
|
54
|
+
return "";
|
|
55
|
+
}
|
|
56
|
+
let normalizedPath = registryPath.trim();
|
|
57
|
+
if (!normalizedPath.startsWith("/")) {
|
|
58
|
+
normalizedPath = `/${normalizedPath}`;
|
|
59
|
+
}
|
|
60
|
+
while (normalizedPath.endsWith("/")) {
|
|
61
|
+
normalizedPath = normalizedPath.slice(0, -1);
|
|
62
|
+
}
|
|
63
|
+
const lowerCasePath = normalizedPath.toLowerCase();
|
|
64
|
+
if (lowerCasePath.endsWith("/v1") || lowerCasePath.endsWith("/v2")) {
|
|
65
|
+
normalizedPath = normalizedPath.slice(0, -3);
|
|
66
|
+
}
|
|
67
|
+
return normalizedPath === "/" ? "" : normalizedPath;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const buildRegistryAuthority = (hostname, port) => {
|
|
71
|
+
if (!hostname) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
hostname = hostname.toLowerCase();
|
|
75
|
+
if (hostname.includes(":") && !hostname.startsWith("[")) {
|
|
76
|
+
hostname = `[${hostname}]`;
|
|
77
|
+
}
|
|
78
|
+
if (port) {
|
|
79
|
+
return `${hostname}:${port}`;
|
|
80
|
+
}
|
|
81
|
+
return hostname;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const parseRawRegistryAuthority = (authority) => {
|
|
85
|
+
if (!authority?.trim()) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
authority = authority.trim();
|
|
89
|
+
if (authority.startsWith("[")) {
|
|
90
|
+
const closingBracketIndex = authority.indexOf("]");
|
|
91
|
+
if (closingBracketIndex === -1) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
const hostname = authority.slice(0, closingBracketIndex + 1);
|
|
95
|
+
const portSuffix = authority.slice(closingBracketIndex + 1);
|
|
96
|
+
if (!portSuffix) {
|
|
97
|
+
return buildRegistryAuthority(hostname);
|
|
98
|
+
}
|
|
99
|
+
if (!/^:\d+$/.test(portSuffix)) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
return buildRegistryAuthority(hostname, portSuffix.slice(1));
|
|
103
|
+
}
|
|
104
|
+
const colonIndex = authority.lastIndexOf(":");
|
|
105
|
+
if (colonIndex > -1 && authority.indexOf(":") === colonIndex) {
|
|
106
|
+
const portCandidate = authority.slice(colonIndex + 1);
|
|
107
|
+
if (/^\d+$/.test(portCandidate)) {
|
|
108
|
+
return buildRegistryAuthority(
|
|
109
|
+
authority.slice(0, colonIndex),
|
|
110
|
+
portCandidate,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return buildRegistryAuthority(authority);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const parseRegistryReference = (registry) => {
|
|
118
|
+
if (!registry?.trim()) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
registry = registry.trim();
|
|
122
|
+
if (registry.includes("://")) {
|
|
123
|
+
if (!URL.canParse(registry)) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
const registryUrl = new URL(registry);
|
|
127
|
+
const authoritySource = registry
|
|
128
|
+
.slice(registry.indexOf("://") + 3)
|
|
129
|
+
.split("/")[0];
|
|
130
|
+
return {
|
|
131
|
+
authority: parseRawRegistryAuthority(authoritySource),
|
|
132
|
+
path: normalizeRegistryPath(registryUrl.pathname),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const slashIndex = registry.indexOf("/");
|
|
136
|
+
const authority =
|
|
137
|
+
slashIndex === -1 ? registry : registry.slice(0, slashIndex);
|
|
138
|
+
const registryPath = slashIndex === -1 ? "" : registry.slice(slashIndex);
|
|
139
|
+
if (!authority) {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
// Raw registry references such as host:port are not absolute URLs, so we
|
|
144
|
+
// add an https scheme only to parse the authority and optional port.
|
|
145
|
+
return {
|
|
146
|
+
authority: parseRawRegistryAuthority(authority),
|
|
147
|
+
path: normalizeRegistryPath(registryPath),
|
|
148
|
+
};
|
|
149
|
+
} catch (_err) {
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const looksLikeImageReference = (value) => {
|
|
155
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
value = value.trim();
|
|
159
|
+
if (value.includes("://")) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
if (!value.includes("/")) {
|
|
163
|
+
if (value.includes(":")) {
|
|
164
|
+
const tagOrPortSuffix = value.slice(value.lastIndexOf(":") + 1);
|
|
165
|
+
if (!/^\d+$/.test(tagOrPortSuffix)) {
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
return !parseRegistryReference(value)?.authority;
|
|
169
|
+
}
|
|
170
|
+
return !(
|
|
171
|
+
value.includes(".") ||
|
|
172
|
+
value === "localhost" ||
|
|
173
|
+
value.startsWith("[")
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
const firstSegment = value.split("/")[0];
|
|
177
|
+
return !(
|
|
178
|
+
parseRegistryReference(firstSegment)?.authority &&
|
|
179
|
+
(firstSegment.includes(".") ||
|
|
180
|
+
firstSegment.includes(":") ||
|
|
181
|
+
firstSegment === "localhost" ||
|
|
182
|
+
firstSegment.startsWith("["))
|
|
183
|
+
);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const resolveRequestedRegistryRef = (forRegistry, requestedRegistryRef) => {
|
|
187
|
+
const fallbackRegistry =
|
|
188
|
+
forRegistry || process.env.DOCKER_SERVER_ADDRESS || DOCKER_HUB_REGISTRY;
|
|
189
|
+
if (
|
|
190
|
+
typeof requestedRegistryRef !== "string" ||
|
|
191
|
+
!requestedRegistryRef.trim()
|
|
192
|
+
) {
|
|
193
|
+
return fallbackRegistry;
|
|
194
|
+
}
|
|
195
|
+
requestedRegistryRef = requestedRegistryRef.trim();
|
|
196
|
+
if (requestedRegistryRef.includes("://")) {
|
|
197
|
+
return requestedRegistryRef;
|
|
198
|
+
}
|
|
199
|
+
return looksLikeImageReference(requestedRegistryRef)
|
|
200
|
+
? fallbackRegistry
|
|
201
|
+
: requestedRegistryRef;
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const extractRequestedRegistryRefFromPath = (path, forRegistry) => {
|
|
205
|
+
if (!path?.includes("?")) {
|
|
206
|
+
return resolveRequestedRegistryRef(forRegistry, forRegistry);
|
|
207
|
+
}
|
|
208
|
+
const queryString = path.slice(path.indexOf("?") + 1);
|
|
209
|
+
const requestedImageRef = new URLSearchParams(queryString).get("fromImage");
|
|
210
|
+
return resolveRequestedRegistryRef(
|
|
211
|
+
forRegistry,
|
|
212
|
+
requestedImageRef || forRegistry,
|
|
213
|
+
);
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const normalizeRegistryReference = (registry) => {
|
|
217
|
+
const parsedRegistry = parseRegistryReference(registry);
|
|
218
|
+
if (!parsedRegistry?.authority) {
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
return parsedRegistry.path
|
|
222
|
+
? `${parsedRegistry.authority}${parsedRegistry.path}`
|
|
223
|
+
: parsedRegistry.authority;
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const registriesMatch = (configuredRegistry, requestedRegistry) => {
|
|
227
|
+
if (!requestedRegistry) {
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
const normalizedConfiguredRegistry =
|
|
231
|
+
parseRegistryReference(configuredRegistry);
|
|
232
|
+
const normalizedRequestedRegistry = parseRegistryReference(requestedRegistry);
|
|
233
|
+
if (
|
|
234
|
+
!normalizedConfiguredRegistry?.authority ||
|
|
235
|
+
!normalizedRequestedRegistry?.authority
|
|
236
|
+
) {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
const hostMatches =
|
|
240
|
+
normalizedConfiguredRegistry.authority ===
|
|
241
|
+
normalizedRequestedRegistry.authority ||
|
|
242
|
+
(DOCKER_HUB_REGISTRY_ALIASES.has(normalizedConfiguredRegistry.authority) &&
|
|
243
|
+
DOCKER_HUB_REGISTRY_ALIASES.has(normalizedRequestedRegistry.authority));
|
|
244
|
+
if (!hostMatches) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
if (!normalizedConfiguredRegistry.path) {
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
return (
|
|
251
|
+
normalizedConfiguredRegistry.path === normalizedRequestedRegistry.path ||
|
|
252
|
+
normalizedRequestedRegistry.path.startsWith(
|
|
253
|
+
`${normalizedConfiguredRegistry.path}/`,
|
|
254
|
+
)
|
|
255
|
+
);
|
|
256
|
+
};
|
|
257
|
+
|
|
45
258
|
// Should we extract the tar image in non-strict mode
|
|
46
259
|
const NON_STRICT_TAR_EXTRACT = ["true", "1"].includes(
|
|
47
260
|
process?.env?.NON_STRICT_TAR_EXTRACT,
|
|
@@ -185,19 +398,21 @@ const REQUEST_TIMEOUT_SECS = 60000;
|
|
|
185
398
|
*
|
|
186
399
|
* @param {string} [forRegistry] Registry hostname (e.g. "registry-1.docker.io").
|
|
187
400
|
* Defaults to DOCKER_SERVER_ADDRESS env var or "docker.io".
|
|
401
|
+
* @param {string} [requestedRegistryRef] Requested registry/image reference used
|
|
402
|
+
* to scope config.json auth matching. Unqualified images default to Docker Hub.
|
|
188
403
|
* @returns {Object} Options object suitable for passing to `got`
|
|
189
404
|
*/
|
|
190
|
-
const getDefaultOptions = (forRegistry) => {
|
|
405
|
+
const getDefaultOptions = (forRegistry, requestedRegistryRef = forRegistry) => {
|
|
191
406
|
let authTokenSet = false;
|
|
192
407
|
if (!forRegistry) {
|
|
193
408
|
forRegistry = process.env.DOCKER_SERVER_ADDRESS ?? DOCKER_HUB_REGISTRY;
|
|
194
409
|
}
|
|
195
|
-
|
|
196
|
-
forRegistry
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
410
|
+
requestedRegistryRef = resolveRequestedRegistryRef(
|
|
411
|
+
forRegistry,
|
|
412
|
+
requestedRegistryRef,
|
|
413
|
+
);
|
|
414
|
+
const normalizedForRegistry =
|
|
415
|
+
parseRegistryReference(forRegistry)?.authority ?? forRegistry;
|
|
201
416
|
const opts = {
|
|
202
417
|
enableUnixSockets: true,
|
|
203
418
|
throwHttpErrors: true,
|
|
@@ -227,12 +442,12 @@ const getDefaultOptions = (forRegistry) => {
|
|
|
227
442
|
process.env.DOCKER_USER &&
|
|
228
443
|
process.env.DOCKER_PASSWORD &&
|
|
229
444
|
process.env.DOCKER_EMAIL &&
|
|
230
|
-
|
|
445
|
+
normalizedForRegistry
|
|
231
446
|
) {
|
|
232
447
|
const authPayload = {
|
|
233
448
|
username: process.env.DOCKER_USER,
|
|
234
449
|
email: process.env.DOCKER_EMAIL,
|
|
235
|
-
serveraddress:
|
|
450
|
+
serveraddress: normalizedForRegistry,
|
|
236
451
|
};
|
|
237
452
|
if (process.env.DOCKER_USER === "<token>") {
|
|
238
453
|
authPayload.IdentityToken = process.env.DOCKER_PASSWORD;
|
|
@@ -242,6 +457,7 @@ const getDefaultOptions = (forRegistry) => {
|
|
|
242
457
|
opts.headers = {
|
|
243
458
|
"X-Registry-Auth": toBase64Url(JSON.stringify(authPayload)),
|
|
244
459
|
};
|
|
460
|
+
authTokenSet = true;
|
|
245
461
|
}
|
|
246
462
|
if (!authTokenSet && safeExistsSync(join(DOCKER_CONFIG, "config.json"))) {
|
|
247
463
|
const configData = readFileSync(
|
|
@@ -254,7 +470,7 @@ const getDefaultOptions = (forRegistry) => {
|
|
|
254
470
|
if (configJson.auths) {
|
|
255
471
|
// Check if there are hardcoded tokens
|
|
256
472
|
for (const serverAddress of Object.keys(configJson.auths)) {
|
|
257
|
-
if (
|
|
473
|
+
if (!registriesMatch(serverAddress, requestedRegistryRef)) {
|
|
258
474
|
continue;
|
|
259
475
|
}
|
|
260
476
|
if (configJson.auths[serverAddress].auth) {
|
|
@@ -293,7 +509,7 @@ const getDefaultOptions = (forRegistry) => {
|
|
|
293
509
|
} else if (configJson.credHelpers) {
|
|
294
510
|
// Support for credential helpers
|
|
295
511
|
for (const serverAddress of Object.keys(configJson.credHelpers)) {
|
|
296
|
-
if (
|
|
512
|
+
if (!registriesMatch(serverAddress, requestedRegistryRef)) {
|
|
297
513
|
continue;
|
|
298
514
|
}
|
|
299
515
|
if (configJson.credHelpers[serverAddress]) {
|
|
@@ -535,7 +751,10 @@ export const makeRequest = async (path, method, forRegistry) => {
|
|
|
535
751
|
}
|
|
536
752
|
// Use the client's prefixUrl (set correctly by getConnection for
|
|
537
753
|
// docker/podman). Only pass per-request auth headers and method options.
|
|
538
|
-
const defaultOptions = getDefaultOptions(
|
|
754
|
+
const defaultOptions = getDefaultOptions(
|
|
755
|
+
forRegistry,
|
|
756
|
+
extractRequestedRegistryRefFromPath(path, forRegistry),
|
|
757
|
+
);
|
|
539
758
|
const opts = {
|
|
540
759
|
responseType: method === "GET" ? "json" : "buffer",
|
|
541
760
|
resolveBodyOnly: true,
|
|
@@ -858,13 +1077,17 @@ export const getImage = async (fullImageName) => {
|
|
|
858
1077
|
return localData;
|
|
859
1078
|
};
|
|
860
1079
|
|
|
1080
|
+
/**
|
|
1081
|
+
* @typedef {{ path: string }} TarReadEntryLike
|
|
1082
|
+
*/
|
|
1083
|
+
|
|
861
1084
|
/**
|
|
862
1085
|
* Warnings such as TAR_ENTRY_INFO are treated as errors in strict mode. While this is mostly desired, we can relax this
|
|
863
1086
|
* requirement for one particular warning related to absolute paths.
|
|
864
1087
|
* This callback function checks for absolute paths in the entry read from the archive and strips them using a custom
|
|
865
1088
|
* method.
|
|
866
1089
|
*
|
|
867
|
-
* @param
|
|
1090
|
+
* @param {TarReadEntryLike} entry ReadEntry object from node-tar
|
|
868
1091
|
*/
|
|
869
1092
|
function handleAbsolutePath(entry) {
|
|
870
1093
|
if (entry.path === "/" || win32.isAbsolute(entry.path)) {
|
|
@@ -1694,8 +1917,9 @@ export const removeImage = async (fullImageName, force = false) => {
|
|
|
1694
1917
|
* if the helper is unavailable or returns an error
|
|
1695
1918
|
*/
|
|
1696
1919
|
export const getCredsFromHelper = (exeSuffix, serverAddress) => {
|
|
1697
|
-
|
|
1698
|
-
|
|
1920
|
+
const cacheKey = `${exeSuffix}:${normalizeRegistryReference(serverAddress) ?? serverAddress}`;
|
|
1921
|
+
if (registry_auth_keys[cacheKey]) {
|
|
1922
|
+
return registry_auth_keys[cacheKey];
|
|
1699
1923
|
}
|
|
1700
1924
|
let credHelperExe = `docker-credential-${exeSuffix}`;
|
|
1701
1925
|
if (isWin) {
|
|
@@ -1726,7 +1950,7 @@ export const getCredsFromHelper = (exeSuffix, serverAddress) => {
|
|
|
1726
1950
|
serveraddress: serverAddress,
|
|
1727
1951
|
};
|
|
1728
1952
|
const authKey = toBase64Url(JSON.stringify(fixedAuthPayload));
|
|
1729
|
-
registry_auth_keys[
|
|
1953
|
+
registry_auth_keys[cacheKey] = authKey;
|
|
1730
1954
|
return authKey;
|
|
1731
1955
|
} catch (_err) {
|
|
1732
1956
|
return undefined;
|