Commit 64feb73
Expose DCR config in operator CRD for OAuth2 upstreams
Implements changes for issue #5040 (Phase 2 DCR CRD surface):
- Add DCRUpstreamConfig CRD type (discoveryUrl, registrationEndpoint,
initialAccessTokenRef, softwareId, softwareStatement) and a new
dcrConfig field on OAuth2UpstreamConfig so Kubernetes users can
configure RFC 7591 Dynamic Client Registration on upstream providers.
- Make OAuth2UpstreamConfig.clientId optional and add CEL validation
requiring exactly one of clientId or dcrConfig, and exactly one of
discoveryUrl or registrationEndpoint inside dcrConfig. Mirror the
checks at runtime via validateOAuth2DCRConfig for defense-in-depth.
- Wire the conversion in controllerutil/authserver.go so DCRConfig is
mapped onto authserver.DCRUpstreamConfig. InitialAccessTokenRef is
resolved to an env var (TOOLHIVE_UPSTREAM_DCR_INITIAL_ACCESS_TOKEN_*)
populated from the referenced Secret, mirroring the ClientSecretRef
pattern. Extract small helpers for env-var generation to keep
cyclomatic complexity within lint limits.
- Regenerate zz_generated.deepcopy.go, CRD YAML manifests, and CRD API
reference docs.
- Add table-driven validation tests covering DCR+ClientID conflict,
both endpoints set, neither endpoint set, valid single-endpoint
cases, and neither-auth configuration. Add conversion tests covering
DCR discoveryUrl/registrationEndpoint paths and initial-access-token
env var wiring.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Address code review feedback
Fixed issues from code review of the DCR CRD surface commit:
- CRITICAL: CEL markers contained a Unicode smart quote (U+201D) that
gofmt's doc-comment formatter reintroduced on every lint-fix. Rewrote
both markers to use CEL's size(...) > 0 idiom instead of `!= ''`, which
sidesteps the typographic normalization entirely and keeps regeneration
idempotent. Verified no U+2018-U+201F characters remain in source or CRDs.
- HIGH: buildUpstreamRunConfig now calls the exported
mcpv1beta1.ValidateOAuth2DCRConfig before producing a RunConfig, so
malformed ClientID/DCRConfig pairs that bypass admission fail at
reconcile time rather than at authserver startup. Error propagation
threaded through BuildAuthServerRunConfig; split OIDC and OAuth2
branches into helpers to stay under the gocyclo limit.
- HIGH: Added table case exercising validateUpstreamProvider rejection
of an OIDC-typed provider whose OAuth2Config carries a DCRConfig.
- MEDIUM: Added kubebuilder CEL XValidation on UpstreamProviderConfig
enforcing oidcConfig/oauth2Config mutual exclusivity paired to the
declared type, closing the silent-pod-failure YAML-apply gap.
- MEDIUM: Added MaxLength=255 to SoftwareID and MaxLength=4096 to
SoftwareStatement to prevent unbounded input from inflating CRs
beyond etcd object limits.
- MEDIUM: Pinned the "neither ClientID nor DCRConfig" error assertion to
the scoped `oauth2Config:` prefix; added a regression case exercising
the non-DCR OAuth2 path (ClientID only, DCRConfig nil); added a new
TestBuildAuthServerRunConfig_InvalidDCR suite covering all four
invalid DCR/ClientID pairings at the conversion layer.
- MEDIUM: Renamed UpstreamDCRInitialAccessTokenEnvVar to
UpstreamDCRInitialAccessTokenEnvVarPrefix and expanded the godoc on
both prefix constants to show the resolved <prefix>_<PROVIDER> form.
All task lint/lint-fix/license-check pass; regenerated CRDs and
deepcopy are idempotent; affected unit tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Address iteration-2 review feedback
Polish items raised in the second review pass:
- MEDIUM: Trim duplicate upstream name from reconcile-time DCR validation
errors. Added scopedFieldPath() helper in
cmd/thv-operator/api/v1beta1/mcpexternalauthconfig_types.go so
ValidateOAuth2DCRConfig prepends a dotted prefix only when one is
given, and the conversion call site now passes an empty prefix so
BuildAuthServerRunConfig's outer "upstream %q: %w" wrap is the only
mention of the upstream name. Strengthened
TestBuildAuthServerRunConfig_InvalidDCR to assert the upstream name
appears exactly once in the error string.
- MEDIUM: Make the UpstreamProviderConfig CEL rule fail closed for
unrecognized future provider types. Restructured the rule from a
binary discriminator into a chain of equality checks ending in an
explicit `false`, and updated the message to "type must be 'oidc'
or 'oauth2'; ...". Added a contributor-facing doc comment reminding
future authors to extend both the rule and validateUpstreamProvider
when adding a new UpstreamProviderType.
- MEDIUM: Refresh the godoc on extractUpstreamSecretRefs to describe
the actual invariants that hold post-CEL: OIDC providers can only
return a clientSecretRef; OAuth2 providers can return both
independently; other (currently unreachable) types return nil/nil.
Cross-linked to the CEL rule and noted that BuildAuthServerRunConfig
is the reconcile-time backstop callers should not rely on this
helper to enforce.
Regenerated CRD YAMLs and crd-api.md prose. task lint, lint-fix,
license-check, and the affected unit tests pass; regeneration is
idempotent.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 5f1d5ff commit 64feb73
10 files changed
Lines changed: 1674 additions & 136 deletions
File tree
- cmd/thv-operator
- api/v1beta1
- pkg/controllerutil
- deploy/charts/operator-crds
- files/crds
- templates
- docs/operator
Lines changed: 154 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
273 | 273 | | |
274 | 274 | | |
275 | 275 | | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
276 | 291 | | |
277 | 292 | | |
278 | 293 | | |
| |||
354 | 369 | | |
355 | 370 | | |
356 | 371 | | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
357 | 380 | | |
358 | 381 | | |
359 | 382 | | |
| |||
374 | 397 | | |
375 | 398 | | |
376 | 399 | | |
377 | | - | |
378 | | - | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
379 | 404 | | |
380 | 405 | | |
381 | 406 | | |
| |||
410 | 435 | | |
411 | 436 | | |
412 | 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 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
413 | 513 | | |
414 | 514 | | |
415 | 515 | | |
| |||
956 | 1056 | | |
957 | 1057 | | |
958 | 1058 | | |
| 1059 | + | |
| 1060 | + | |
| 1061 | + | |
| 1062 | + | |
| 1063 | + | |
| 1064 | + | |
| 1065 | + | |
959 | 1066 | | |
960 | 1067 | | |
961 | 1068 | | |
962 | 1069 | | |
| 1070 | + | |
| 1071 | + | |
| 1072 | + | |
| 1073 | + | |
| 1074 | + | |
| 1075 | + | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
| 1081 | + | |
| 1082 | + | |
| 1083 | + | |
| 1084 | + | |
| 1085 | + | |
| 1086 | + | |
| 1087 | + | |
| 1088 | + | |
| 1089 | + | |
| 1090 | + | |
| 1091 | + | |
| 1092 | + | |
| 1093 | + | |
| 1094 | + | |
| 1095 | + | |
| 1096 | + | |
| 1097 | + | |
| 1098 | + | |
| 1099 | + | |
| 1100 | + | |
| 1101 | + | |
| 1102 | + | |
| 1103 | + | |
| 1104 | + | |
| 1105 | + | |
| 1106 | + | |
| 1107 | + | |
| 1108 | + | |
| 1109 | + | |
| 1110 | + | |
| 1111 | + | |
| 1112 | + | |
| 1113 | + | |
| 1114 | + | |
963 | 1115 | | |
964 | 1116 | | |
965 | 1117 | | |
| |||
Lines changed: 119 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
571 | 571 | | |
572 | 572 | | |
573 | 573 | | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
574 | 693 | | |
575 | 694 | | |
576 | 695 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
0 commit comments