Commit 0746507
committed
fix: hint to host-qualify cross-repo on *.ghe.com (closes microsoft#1305)
PR microsoft#1292 fixed the silent ``github.com`` auth fallback for **in-marketplace**
plugin sources on ``*.ghe.com`` marketplaces but deliberately scoped its host
backfill via ``_is_in_marketplace_source`` to avoid changing routing for
cross-repo dict sources. A bare cross-repo ``repo: owner/proj`` on an enterprise
marketplace still legitimately means two different things -- a real
``github.com`` open-source dep, or a misconfigured same-host entry that should
have been ``corp.ghe.com/owner/proj`` -- and the resolver cannot disambiguate
them. The silent mis-route survives for the second intent: the canonical stays
bare, ``DependencyReference.parse`` defaults the host to ``github.com``, and
the install path reports the generic
``not accessible or doesn't exist -- run with --verbose for auth details``
with zero pointer at the marketplace's enterprise host.
Surface the diagnostic at the install-time validation-failure boundary, not
at resolver time. The legitimate cross-host case validates successfully and
never sees a hint; the misconfigured case fails validation and gets an
actionable host-qualified suggestion. The resolver-time always-on warning
the PR microsoft#1292 review panel rejected -- which would false-positive on the
legitimate case and train operators to ignore -- is avoided.
Approach
========
Resolver attaches a typed ``CrossRepoMisconfigRisk`` sentinel to
``MarketplacePluginResolution`` when **all** of:
- ``dependency_reference`` is ``None`` (GitHub-family virtual-shorthand path;
GitLab-class and self-managed FQDN marketplaces build a structured ref
upstream and sidestep the bug)
- ``plugin.source`` is a dict whose normalized type is ``github`` -- via the
existing ``_coerce_dict_plugin_type`` (covers ``type``/``kind``/``source``
synonyms plus the inferred-github fallback). Cross-repo ``gitlab`` /
``git-subdir`` dict sources on enterprise marketplaces hit the same
auth-routing bug but the "host-qualify with marketplace host" remediation
only matches operator intent for the GitHub family.
- the source is NOT an in-marketplace reference (PR microsoft#1292's domain)
- ``_needs_canonical_host_prefix`` agrees the canonical is bare and the host
is GitHub-family enterprise (``*.ghe.com``; idempotent against already
host-qualified, URL, and SSH forms)
- the ``repo`` field is a non-empty ``owner/repo`` shorthand
The helper is pure -- no logging, no canonical mutation. Resolver behavior is
unchanged; only the resolution object carries one extra optional field.
Install command records the risk in a per-call ``_misconfig_risks`` dict
**before** validation runs. The existing ``_marketplace_provenance`` map only
gets written on validation success and cannot be relied on at the failure
boundary. When ``_validate_package_exists`` returns ``False`` (which is how
the GitHub-family auth failure surfaces -- ``AuthResolver.try_with_fallback``
collapses 401/404/network into a single ``False``, no typed ``AuthenticationError``),
the validation-fail branch emits the hint inline via ``logger.info`` so the
operator can correct ``marketplace.json`` without rerunning under ``--verbose``
to decode the auth trace.
Why this layer, not ``AuthenticationError``
===========================================
The two ``raise AuthenticationError`` sites in the install pipeline are both
gated to non-GitHub hosts (ADO / self-managed): ``pipeline.py`` preflight skips
``is_github_hostname(host)`` early; ``validation.py`` requires the
``is_ado_auth_failure_signal`` stderr pattern. The github.com fallback path
goes through ``try_with_fallback`` which returns ``False`` on failure, and the
caller records ``(canonical, reason)`` into ``invalid_outcomes``. Decorating
``AuthenticationError`` would be a dead-code hook for this bug -- the typed
exception never fires on the github.com path. The validation-fail branch is
the actual choke point.
Scope and tradeoffs
===================
- 404 typo on the cross-repo ``repo`` field and network failures will also
trigger the hint; the wording leads with the routing fact ("resolved to
'github.com'") and the suggestion is conditional ("If you meant the
enterprise host"), so the false-positive remains advisory rather than
misleading. Distinguishing 401 from 404/network here would require
threading HTTP status out of ``try_with_fallback`` -- a much broader
cross-cutting change.
- The silent-success-on-wrong-host case (cross-repo bare where the same
``owner/repo`` happens to exist on github.com with different content)
cannot be detected without changing the routing semantics PR microsoft#1292
preserved. This is acknowledged out of scope in the issue.
Tests
=====
``TestCrossRepoMisconfigRisk`` (resolver, 14 cases) locks the truth table for
sentinel attach / no-attach across the dict-type synonyms (``type``, ``kind``,
``source``, inferred-github), host-qualified / URL / SSH / no-slash defensive
guards, the gitlab / git-subdir exclusion, and pure ``github.com`` marketplace
non-pollution.
``TestResolvePackageReferencesCrossRepoMisconfigHint`` (install, 4 cases)
locks the hint emission contract: hint fires only when a risk-bearing
marketplace resolution subsequently fails validation; the legitimate
cross-host path that validates successfully emits no hint; in-marketplace
and plain owner/repo failures emit no hint.
Both test suites were toggle-verified -- removing the resolver helper call or
the install-side emission block makes the corresponding positive case fail.1 parent 22ebb35 commit 0746507
4 files changed
Lines changed: 656 additions & 1 deletion
File tree
- src/apm_cli
- commands
- marketplace
- tests/unit
- commands
- marketplace
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
349 | 349 | | |
350 | 350 | | |
351 | 351 | | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
352 | 359 | | |
353 | 360 | | |
354 | 361 | | |
| |||
403 | 410 | | |
404 | 411 | | |
405 | 412 | | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
406 | 420 | | |
407 | 421 | | |
408 | 422 | | |
| |||
521 | 535 | | |
522 | 536 | | |
523 | 537 | | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
524 | 556 | | |
525 | 557 | | |
526 | 558 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
47 | 47 | | |
48 | 48 | | |
49 | 49 | | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
50 | 73 | | |
51 | 74 | | |
52 | 75 | | |
| |||
57 | 80 | | |
58 | 81 | | |
59 | 82 | | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
60 | 86 | | |
61 | 87 | | |
62 | 88 | | |
63 | 89 | | |
64 | 90 | | |
| 91 | + | |
65 | 92 | | |
66 | 93 | | |
67 | 94 | | |
| |||
221 | 248 | | |
222 | 249 | | |
223 | 250 | | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
224 | 300 | | |
225 | 301 | | |
226 | 302 | | |
| |||
607 | 683 | | |
608 | 684 | | |
609 | 685 | | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
610 | 699 | | |
611 | 700 | | |
612 | 701 | | |
| |||
674 | 763 | | |
675 | 764 | | |
676 | 765 | | |
677 | | - | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
678 | 770 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
280 | 280 | | |
281 | 281 | | |
282 | 282 | | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
0 commit comments