mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-27 15:58:48 +00:00
17466ceb32
feat(host-rules): ignore URL credentials when matching matchHost
`matchesHost()` compared the raw href of the searched URL against
`matchHost`, so a URL carrying `user:pass@` userinfo (often a literal
placeholder such as `${USER}:${PASS}@`) never matched a `matchHost`
without credentials, including path-scoped ones. Callers worked around
this by stripping `username`/`password` off the URL by hand before
calling `hostRules.find()`.
- Add `stripUrlCredentials()` to `lib/util/url.ts`, returning the URL's
`href` without userinfo (or `null` if unparseable), covered by
`lib/util/url.spec.ts`.
- `matchesHost()` in `lib/util/host-rules.ts` now strips credentials
from the searched URL before comparing it against an HTTP(S)
`matchHost`, so `hostRules.find()` ignores userinfo on every caller's
URL. Covered by new cases in `lib/util/host-rules.spec.ts` (a
`matchHost` rule matches a URL carrying `user:pass@`, including a
path-scoped `matchHost`).
- Remove the hand-rolled strip in
`lib/modules/datasource/pypi/host-rules.ts`'s
`findPypiIndexCredentials()`, now redundant since `find()` does it.
`lib/modules/datasource/pypi/host-rules.spec.ts` already covers this
behaviour and needed no changes.
This is strictly additive: more URLs match `matchHost` than before,
and nothing that matched before stops matching.
49 lines
1.5 KiB
TypeScript
49 lines
1.5 KiB
TypeScript
import { logger } from '../../../logger/index.ts';
|
|
import { find } from '../../../util/host-rules.ts';
|
|
import { parseUrl } from '../../../util/url.ts';
|
|
import { getGoogleAuthHostRule, isGoogleArtifactRegistry } from '../util.ts';
|
|
import { pypiDatasourceId } from './common.ts';
|
|
import type { PypiIndexCredentials } from './types.ts';
|
|
|
|
/**
|
|
* Resolves the credentials for a Python package index URL.
|
|
*
|
|
* The URL's own `user:password@` part - which is often a placeholder such as
|
|
* `${USER}:${PASS}@` - does not stop it matching a `matchHost` without
|
|
* credentials, as `find()` ignores userinfo when matching. Google Artifact
|
|
* Registry is only asked for a token when no host rule supplies credentials,
|
|
* so an explicitly configured username/password always wins.
|
|
*/
|
|
export async function findPypiIndexCredentials(
|
|
indexUrl: string | undefined,
|
|
): Promise<PypiIndexCredentials> {
|
|
const parsedUrl = parseUrl(indexUrl);
|
|
if (!parsedUrl) {
|
|
logger.once.debug(`Failed to parse index URL ${indexUrl}`);
|
|
return {};
|
|
}
|
|
|
|
const { username, password } = find({
|
|
hostType: pypiDatasourceId,
|
|
url: parsedUrl.toString(),
|
|
});
|
|
if (username ?? password) {
|
|
return { username, password };
|
|
}
|
|
|
|
if (isGoogleArtifactRegistry(parsedUrl.hostname)) {
|
|
const googleHostRule = await getGoogleAuthHostRule();
|
|
if (googleHostRule) {
|
|
return {
|
|
username: googleHostRule.username,
|
|
password: googleHostRule.password,
|
|
};
|
|
}
|
|
logger.once.debug(
|
|
`Could not get Google access token (url=${parsedUrl.toString()})`,
|
|
);
|
|
}
|
|
|
|
return {};
|
|
}
|