diff --git a/lib/start-proxy-action.js b/lib/start-proxy-action.js index a27f12f95..9553ff720 100644 --- a/lib/start-proxy-action.js +++ b/lib/start-proxy-action.js @@ -63302,7 +63302,7 @@ var require_Credential = __commonJS({ "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.Credential = void 0; - var Credential = class { + var Credential2 = class { /** * Creates a RequestPolicy object. * @@ -63313,7 +63313,7 @@ var require_Credential = __commonJS({ throw new Error("Method should be implemented in children classes."); } }; - exports2.Credential = Credential; + exports2.Credential = Credential2; } }); @@ -64442,7 +64442,7 @@ var require_Credential2 = __commonJS({ "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.Credential = void 0; - var Credential = class { + var Credential2 = class { /** * Creates a RequestPolicy object. * @@ -64453,7 +64453,7 @@ var require_Credential2 = __commonJS({ throw new Error("Method should be implemented in children classes."); } }; - exports2.Credential = Credential; + exports2.Credential = Credential2; } }); @@ -121365,6 +121365,80 @@ var KnownLanguage = /* @__PURE__ */ ((KnownLanguage2) => { return KnownLanguage2; })(KnownLanguage || {}); +// src/start-proxy/types.ts +function hasUsername(config) { + return "username" in config; +} +function isUsernamePassword(config) { + return hasUsername(config) && "password" in config; +} +function isToken(config) { + return "token" in config; +} +function isAzureConfig(config) { + return "tenant_id" in config && "client_id" in config && isDefined2(config.tenant_id) && isDefined2(config.client_id); +} +function isAWSConfig(config) { + const requiredProperties = [ + "aws_region", + "account_id", + "role_name", + "domain", + "domain_owner" + ]; + for (const property of requiredProperties) { + if (!(property in config) || !isDefined2(config[property])) { + return false; + } + } + return true; +} +function isJFrogConfig(config) { + return "jfrog_oidc_provider_name" in config && isDefined2(config.jfrog_oidc_provider_name); +} +function credentialToStr(credential) { + let result = `Type: ${credential.type};`; + const appendIfDefined = (name, val) => { + if (isDefined2(val)) { + result += ` ${name}: ${val};`; + } + }; + appendIfDefined("Url", credential.url); + appendIfDefined("Host", credential.host); + if (hasUsername(credential)) { + appendIfDefined("Username", credential.username); + } + if ("password" in credential) { + appendIfDefined("Password", credential.password ? "***" : void 0); + } + if (isToken(credential)) { + appendIfDefined("Token", credential.token ? "***" : void 0); + } + if (isAzureConfig(credential)) { + appendIfDefined("Tenant", credential.tenant_id); + appendIfDefined("Client", credential.client_id); + } else if (isAWSConfig(credential)) { + appendIfDefined("AWS Region", credential.aws_region); + appendIfDefined("AWS Account", credential.account_id); + appendIfDefined("AWS Role", credential.role_name); + appendIfDefined("AWS Domain", credential.domain); + appendIfDefined("AWS Domain Owner", credential.domain_owner); + appendIfDefined("AWS Audience", credential.audience); + } else if (isJFrogConfig(credential)) { + appendIfDefined("JFrog Provider", credential.jfrog_oidc_provider_name); + appendIfDefined("JFrog Identity Mapping", credential.identity_mapping_name); + appendIfDefined("JFrog Audience", credential.audience); + } + return result; +} +function getAddressString(address) { + if (address.url === void 0) { + return address.host; + } else { + return address.url; + } +} + // src/status-report.ts var os = __toESM(require("os")); var core9 = __toESM(require_core()); @@ -121642,15 +121716,6 @@ async function sendUnhandledErrorStatusReport(actionName, actionStartedAt, error } } -// src/start-proxy/types.ts -function getAddressString(address) { - if (address.url === void 0) { - return address.host; - } else { - return address.url; - } -} - // src/start-proxy.ts function getStartProxyErrorMessage(errorType) { switch (errorType) { @@ -121777,6 +121842,42 @@ function getRegistryAddress(registry) { ); } } +function getAuthConfig(config) { + if (isAzureConfig(config)) { + return { + tenant_id: config.tenant_id, + client_id: config.client_id + }; + } else if (isAWSConfig(config)) { + return { + aws_region: config.aws_region, + account_id: config.account_id, + role_name: config.role_name, + domain: config.domain, + domain_owner: config.domain_owner, + audience: config.audience + }; + } else if (isJFrogConfig(config)) { + return { + jfrog_oidc_provider_name: config.jfrog_oidc_provider_name, + identity_mapping_name: config.identity_mapping_name, + audience: config.audience + }; + } else if (isToken(config)) { + if (isDefined2(config.token)) { + core10.setSecret(config.token); + } + return { username: config.username, token: config.token }; + } else { + if ("password" in config && isDefined2(config.password)) { + core10.setSecret(config.password); + } + return { + username: "username" in config ? config.username : void 0, + password: "password" in config ? config.password : void 0 + }; + } +} function getCredentials(logger, registrySecrets, registriesCredentials, language, skipUnusedRegistries = false) { const registryMapping = skipUnusedRegistries ? NEW_LANGUAGE_TO_REGISTRY_TYPE : LANGUAGE_TO_REGISTRY_TYPE; const registryTypeForLanguage = language ? registryMapping[language] : void 0; @@ -121811,12 +121912,7 @@ function getCredentials(logger, registrySecrets, registriesCredentials, language if (!isDefined2(e.type)) { throw new ConfigurationError("Invalid credentials - must have a type"); } - if (isDefined2(e.password)) { - core10.setSecret(e.password); - } - if (isDefined2(e.token)) { - core10.setSecret(e.token); - } + const authConfig = getAuthConfig(e); const address = getRegistryAddress(e); if (registryTypeForLanguage && !registryTypeForLanguage.some((t) => t === e.type)) { continue; @@ -121832,16 +121928,14 @@ function getCredentials(logger, registrySecrets, registriesCredentials, language ); } } - if (!isDefined2(e.username) && (isDefined2(e.password) && isPAT(e.password) || isDefined2(e.token) && isPAT(e.token))) { + if ((!hasUsername(authConfig) || !isDefined2(authConfig.username)) && isUsernamePassword(authConfig) && isDefined2(authConfig.password) && isPAT(authConfig.password) || isToken(authConfig) && isDefined2(authConfig.token) && isPAT(authConfig.token)) { logger.warning( `A ${e.type} private registry is configured for ${e.host || e.url} using a GitHub Personal Access Token (PAT), but no username was provided. This may not work correctly. When configuring a private registry using a PAT, select "Username and password" and enter the username of the user who generated the PAT.` ); } out.push({ type: e.type, - username: e.username, - password: e.password, - token: e.token, + ...authConfig, ...address }); } @@ -121903,9 +121997,6 @@ async function getDownloadUrl(logger, features) { version: UPDATEJOB_PROXY_VERSION }; } -function credentialToStr(c) { - return `Type: ${c.type}; Host: ${c.host}; Url: ${c.url} Username: ${c.username}; Password: ${c.password !== void 0}; Token: ${c.token !== void 0}`; -} async function downloadProxy(logger, url, authorization) { try { return toolcache.downloadTool( diff --git a/src/start-proxy.test.ts b/src/start-proxy.test.ts index 01a078c9e..86bbf1284 100644 --- a/src/start-proxy.test.ts +++ b/src/start-proxy.test.ts @@ -529,40 +529,6 @@ test.serial("getDownloadUrl returns matching release asset", async (t) => { }); }); -test.serial("credentialToStr - hides passwords", (t) => { - const secret = "password123"; - const credential = { - type: "maven_credential", - password: secret, - url: "https://localhost", - }; - - const str = startProxyExports.credentialToStr(credential); - - t.false(str.includes(secret)); - t.is( - "Type: maven_credential; Host: undefined; Url: https://localhost Username: undefined; Password: true; Token: false", - str, - ); -}); - -test.serial("credentialToStr - hides tokens", (t) => { - const secret = "password123"; - const credential = { - type: "maven_credential", - token: secret, - url: "https://localhost", - }; - - const str = startProxyExports.credentialToStr(credential); - - t.false(str.includes(secret)); - t.is( - "Type: maven_credential; Host: undefined; Url: https://localhost Username: undefined; Password: false; Token: true", - str, - ); -}); - test.serial( "getSafeErrorMessage - returns actual message for `StartProxyError`", (t) => { diff --git a/src/start-proxy.ts b/src/start-proxy.ts index cd6301bf4..b6c02bfa3 100644 --- a/src/start-proxy.ts +++ b/src/start-proxy.ts @@ -551,17 +551,6 @@ export async function getDownloadUrl( }; } -/** - * Pretty-prints a `Credential` value to a string, but hides the actual password or token values. - * - * @param c The credential to convert to a string. - */ -export function credentialToStr(c: Credential): string { - return `Type: ${c.type}; Host: ${c.host}; Url: ${c.url} Username: ${ - c.username - }; Password: ${c.password !== undefined}; Token: ${c.token !== undefined}`; -} - /** * Attempts to download a file from `url` into the toolcache. * diff --git a/src/start-proxy/types.test.ts b/src/start-proxy/types.test.ts new file mode 100644 index 000000000..ee20e74aa --- /dev/null +++ b/src/start-proxy/types.test.ts @@ -0,0 +1,136 @@ +import test from "ava"; + +import { setupTests } from "../testing-utils"; + +import * as types from "./types"; + +setupTests(test); + +const validAzureCredential: types.AzureConfig = { + tenant_id: "12345678-1234-1234-1234-123456789012", + client_id: "abcdef01-2345-6789-abcd-ef0123456789", +}; + +const validAwsCredential: types.AWSConfig = { + aws_region: "us-east-1", + account_id: "123456789012", + role_name: "MY_ROLE", + domain: "MY_DOMAIN", + domain_owner: "987654321098", + audience: "custom-audience", +}; + +const validJFrogCredential: types.JFrogConfig = { + jfrog_oidc_provider_name: "MY_PROVIDER", + audience: "jfrog-audience", + identity_mapping_name: "my-mapping", +}; + +test("credentialToStr - pretty-prints valid username+password configurations", (t) => { + const secret = "password123"; + const credential: types.Credential = { + type: "maven_credential", + username: "user", + password: secret, + url: "https://localhost", + }; + + const str = types.credentialToStr(credential); + + t.false(str.includes(secret)); + t.is( + "Type: maven_credential; Url: https://localhost; Username: user; Password: ***;", + str, + ); +}); + +test("credentialToStr - pretty-prints valid username+token configurations", (t) => { + const secret = "password123"; + const credential: types.Credential = { + type: "maven_credential", + username: "user", + token: secret, + url: "https://localhost", + }; + + const str = types.credentialToStr(credential); + + t.false(str.includes(secret)); + t.is( + "Type: maven_credential; Url: https://localhost; Username: user; Token: ***;", + str, + ); +}); + +test("credentialToStr - pretty-prints valid Azure OIDC configurations", (t) => { + const credential: types.Credential = { + type: "maven_credential", + url: "https://localhost", + ...validAzureCredential, + }; + + const str = types.credentialToStr(credential); + + t.is( + "Type: maven_credential; Url: https://localhost; Tenant: 12345678-1234-1234-1234-123456789012; Client: abcdef01-2345-6789-abcd-ef0123456789;", + str, + ); +}); + +test("credentialToStr - pretty-prints valid AWS OIDC configurations", (t) => { + const credential: types.Credential = { + type: "maven_credential", + url: "https://localhost", + ...validAwsCredential, + }; + + const str = types.credentialToStr(credential); + + t.is( + "Type: maven_credential; Url: https://localhost; AWS Region: us-east-1; AWS Account: 123456789012; AWS Role: MY_ROLE; AWS Domain: MY_DOMAIN; AWS Domain Owner: 987654321098; AWS Audience: custom-audience;", + str, + ); +}); + +test("credentialToStr - pretty-prints valid JFrog OIDC configurations", (t) => { + const credential: types.Credential = { + type: "maven_credential", + url: "https://localhost", + ...validJFrogCredential, + }; + + const str = types.credentialToStr(credential); + + t.is( + "Type: maven_credential; Url: https://localhost; JFrog Provider: MY_PROVIDER; JFrog Identity Mapping: my-mapping; JFrog Audience: jfrog-audience;", + str, + ); +}); + +test("credentialToStr - hides passwords", (t) => { + const secret = "password123"; + const credential = { + type: "maven_credential", + password: secret, + url: "https://localhost", + }; + + const str = types.credentialToStr(credential); + + t.false(str.includes(secret)); + t.is("Type: maven_credential; Url: https://localhost; Password: ***;", str); +}); + +test("credentialToStr - hides tokens", (t) => { + const secret = "password123"; + const credential = { + type: "maven_credential", + token: secret, + url: "https://localhost", + }; + + const str = types.credentialToStr(credential); + + t.false(str.includes(secret)); + t.is("Type: maven_credential; Url: https://localhost; Token: ***;", str); +}); diff --git a/src/start-proxy/types.ts b/src/start-proxy/types.ts index 235fc7615..0efed8a04 100644 --- a/src/start-proxy/types.ts +++ b/src/start-proxy/types.ts @@ -121,6 +121,53 @@ export type AuthConfig = UsernamePassword | Token | OIDC; */ export type Credential = AuthConfig & Registry; +/** + * Pretty-prints a `Credential` value to a string, but hides the actual password or token values. + * + * @param credential The credential to convert to a string. + */ +export function credentialToStr(credential: Credential): string { + let result: string = `Type: ${credential.type};`; + + const appendIfDefined = (name: string, val: string | undefined) => { + if (isDefined(val)) { + result += ` ${name}: ${val};`; + } + }; + + appendIfDefined("Url", credential.url); + appendIfDefined("Host", credential.host); + + if (hasUsername(credential)) { + appendIfDefined("Username", credential.username); + } + + if ("password" in credential) { + appendIfDefined("Password", credential.password ? "***" : undefined); + } + if (isToken(credential)) { + appendIfDefined("Token", credential.token ? "***" : undefined); + } + + if (isAzureConfig(credential)) { + appendIfDefined("Tenant", credential.tenant_id); + appendIfDefined("Client", credential.client_id); + } else if (isAWSConfig(credential)) { + appendIfDefined("AWS Region", credential.aws_region); + appendIfDefined("AWS Account", credential.account_id); + appendIfDefined("AWS Role", credential.role_name); + appendIfDefined("AWS Domain", credential.domain); + appendIfDefined("AWS Domain Owner", credential.domain_owner); + appendIfDefined("AWS Audience", credential.audience); + } else if (isJFrogConfig(credential)) { + appendIfDefined("JFrog Provider", credential.jfrog_oidc_provider_name); + appendIfDefined("JFrog Identity Mapping", credential.identity_mapping_name); + appendIfDefined("JFrog Audience", credential.audience); + } + + return result; +} + /** A package registry is identified by its type and address. */ export type Registry = { /** The type of the package registry. */