Skip to content
Prev Previous commit
Next Next commit
Extract AuthConfig from Credential
  • Loading branch information
mbg committed Mar 10, 2026
commit 7263be20845d8e6c92f9ed98e583a7ff04a8bb24
82 changes: 69 additions & 13 deletions src/start-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ import {
RawCredential,
Registry,
Credential,
AuthConfig,
isToken,
isAzureConfig,
Token,
UsernamePassword,
AzureConfig,
isAWSConfig,
AWSConfig,
isJFrogConfig,
JFrogConfig,
isUsernamePassword,
hasUsername,
} from "./start-proxy/types";
import {
ActionName,
Expand Down Expand Up @@ -274,6 +286,54 @@ function getRegistryAddress(registry: Partial<Registry>): Address {
}
}

/** Extracts an `AuthConfig` value from `config`. */
export function getAuthConfig(config: Partial<AuthConfig>): AuthConfig {
// Start by checking for the OIDC configurations, since they have required properties
// which we can use to identify them.
if (isAzureConfig(config)) {
return {
tenant_id: config.tenant_id,
client_id: config.client_id,
} satisfies AzureConfig;
} 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,
} satisfies AWSConfig;
} else if (isJFrogConfig(config)) {
return {
jfrog_oidc_provider_name: config.jfrog_oidc_provider_name,
identity_mapping_name: config.identity_mapping_name,
audience: config.audience,
} satisfies JFrogConfig;
} else if (isToken(config)) {
// For token-based authentication, both the token and username are optional.
// If the token is absent, then it doesn't matter if we end up treating it
// as a `UsernamePassword` object internally.

// Mask token to reduce chance of accidental leakage in logs, if we have one.
if (isDefined(config.token)) {
core.setSecret(config.token);
}

Comment thread
mbg marked this conversation as resolved.
return { username: config.username, token: config.token } satisfies Token;
} else {
// Mask password to reduce chance of accidental leakage in logs, if we have one.
if ("password" in config && isDefined(config.password)) {
core.setSecret(config.password);
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
Comment thread
mbg marked this conversation as resolved.
Dismissed
}

return {
username: "username" in config ? config.username : undefined,
password: "password" in config ? config.password : undefined,
} satisfies UsernamePassword;
}
Comment thread
mbg marked this conversation as resolved.
}

// getCredentials returns registry credentials from action inputs.
// It prefers `registries_credentials` over `registry_secrets`.
// If neither is set, it returns an empty array.
Expand Down Expand Up @@ -332,13 +392,7 @@ export function getCredentials(
}

// Mask credentials to reduce chance of accidental leakage in logs.
if (isDefined(e.password)) {
core.setSecret(e.password);
}
if (isDefined(e.token)) {
core.setSecret(e.token);
}

const authConfig = getAuthConfig(e);
const address = getRegistryAddress(e);

// Filter credentials based on language if specified. `type` is the registry type.
Expand Down Expand Up @@ -366,9 +420,13 @@ export function getCredentials(

// If the password or token looks like a GitHub PAT, warn if no username is configured.
if (
!isDefined(e.username) &&
((isDefined(e.password) && isPAT(e.password)) ||
(isDefined(e.token) && isPAT(e.token)))
((!hasUsername(authConfig) || !isDefined(authConfig.username)) &&
isUsernamePassword(authConfig) &&
isDefined(authConfig.password) &&
isPAT(authConfig.password)) ||
(isToken(authConfig) &&
isDefined(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. ` +
Expand All @@ -379,9 +437,7 @@ export function getCredentials(

out.push({
type: e.type,
username: e.username,
password: e.password,
token: e.token,
...authConfig,
...address,
});
}
Expand Down