OSAC-3082: implement reference validation interceptor - #963
openshift-merge-bot[bot] merged 15 commits into
Conversation
|
@htayrie-rh: This pull request references OSAC-3082 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the epic to target the "5.0.0" version, but no target version was set. DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a reference-validation gRPC interceptor for Create and Update requests. It recursively resolves protobuf references, fills missing identifiers, reports invalid references, records metrics, wires into server startup, and adds schemas and comprehensive tests. ChangesReference validation
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant GRPCServer
participant ReferenceValidator
participant ReferenceLookup
Client->>GRPCServer: Create or Update request
GRPCServer->>ReferenceValidator: Invoke interceptor
ReferenceValidator->>ReferenceLookup: Resolve reference
ReferenceLookup-->>ReferenceValidator: Resolved reference or error
ReferenceValidator-->>GRPCServer: Continue or return validation error
GRPCServer-->>Client: RPC response
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 11✅ Passed checks (11 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 13
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@internal/cmd/service/start/grpcserver/start_grpc_server_cmd.go`:
- Line 519: Remove referenceValidator.StreamServer from the stream interceptor
chain in the gRPC server startup configuration. Preserve the remaining
interceptors and registration behavior, since StreamServer is unconditionally
pass-through.
- Around line 434-443: Before wiring referenceValidator into the gRPC
interceptor chain, either disable its registration by default or populate it
with lookup registrations for every reference type handled by Create and Update
requests. Update the startup flow around NewReferenceValidator().Build() and the
interceptor registration so valid reference-bearing requests reach their
handlers without “no lookup registered” errors.
In `@internal/references/reference_validator_test.go`:
- Around line 987-1030: Extend the reference validator specs around the existing
id/name mismatch case to cover a lookup returning the supplied ID and name,
asserting the handler executes and increments a valid counter. Also add cases
for map-nested references, a lookup returning (nil, nil), and references with
neither ID nor name, using the expected validation outcomes for each.
- Around line 1140-1145: Update the UnaryServer calls in the metric
specifications around validator.UnaryServer to capture and assert the returned
gRPC status code, rather than discarding the error. Keep the existing counter
assertions, and verify the status matches the expected failure reason so
unrelated counter increments cannot pass the tests.
- Around line 200-427: Replace the “Field discovery” tests’ direct
discoverReferenceFields calls with end-to-end resolveAndMutate execution using
recording lookups registered for each reference type. Assert the captured
fullName and fieldPath tuples, including nested, repeated, and oneof paths with
the production “[i]” formatting, and remove reliance on the duplicate
collectRefs traversal; apply the same change to the corresponding later test
block.
In `@internal/references/reference_validator.go`:
- Around line 304-310: Update the warning logs in the reference-not-found paths,
including the flow around logger.WarnContext, to mark customer-scoped values for
redaction by prefixing the sensitive keys with “!”: identifier, tenant, and
project here, plus id and name in the corresponding log at the other referenced
location. Leave field_path and reference_type unchanged.
- Around line 291-295: Update the reference lookup flow around lookupFunc and
recordDuration to bound the number of references processed per request, execute
lookups concurrently using an errgroup with a small concurrency limit, and apply
a context.WithTimeout to each lookup. Preserve request cancellation and timeout
propagation through context.Context, while retaining duration recording for
every lookup.
- Around line 401-429: The reference lookup flow in
internal/references/reference_validator.go#L401-L429 must derive tenant and
project from the authenticated identity in ctx, not object metadata, and reject
payload metadata values that disagree; update the surrounding validation symbols
accordingly. In internal/references/reference_validator.go#L385-L388, authorize
the client-supplied shared flag before switching tenants and replace the literal
"shared" with the existing or newly defined named constant.
- Around line 285-292: Update the reference validation flow around lookupFunc to
detect when both id and name are empty before invoking the lookup. In that
present-but-blank case, short-circuit and record/return the same violation
result used for invalid references; preserve the existing lookup behavior when
either identifier is provided.
- Around line 477-488: Update registerOrReuse so the AlreadyRegisteredError path
uses a comma-ok type assertion for registered.ExistingCollector instead of
panicking; return the existing collector only when it matches C, and otherwise
return the zero C value with an appropriate error.
- Around line 292-329: Validate resolved immediately after a successful lookup
in the reference-validation flow before accessing resolved.ID or resolved.Name.
Treat a nil result as an internal lookup failure, log it through the existing
“Reference lookup failed” path with field_path and reference_type context,
record the result as "error", and return the established Internal gRPC status
instead of dereferencing it.
- Around line 199-204: Sort the collected validation violations by their Field
value before serializing the Bad Request detail and joining descriptions. Update
the validate() flow or the serialization step around walkMessage so
protoreflect.Message.Range traversal order cannot affect FieldViolations order
or the resulting error message.
- Around line 206-208: Update the map-field branch in the reference validation
method to avoid silently accepting map fields: either recursively validate each
map value via Map().Range, or explicitly return an Internal error or warning
that map references are unsupported. Preserve the validator’s fail-closed
behavior and avoid shadowing the ranged value variable.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: b9eb8fa2-1fc6-4924-98ab-a91c8d7f35bf
⛔ Files ignored due to path filters (2)
internal/api/osac/tests/v1/reference_test_types.pb.gois excluded by!**/*.pb.gointernal/api/osac/tests/v1/reference_test_types_protoopaque.pb.gois excluded by!**/*.pb.go
📒 Files selected for processing (6)
go.modinternal/cmd/service/start/grpcserver/start_grpc_server_cmd.gointernal/references/reference_validator.gointernal/references/reference_validator_test.gointernal/references/references_suite_test.goproto/tests/osac/tests/v1/reference_test_types.proto
There was a problem hiding this comment.
♻️ Duplicate comments (1)
internal/references/reference_validator.go (1)
199-217: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winMap-valued reference fields are still skipped — only a warning was added, not validation.
The fix adds a log line but the underlying gap flagged previously remains: message-valued map entries (e.g.,
map<string, FooReference>) are never walked, so references nested in maps still bypass validation entirely and can't be auto-populated or rejected. This is inconsistent with the interceptor's fail-closed design for unregistered types elsewhere. Consider actually walkingval.Map().Range(...)for message-valued maps (recursing intoresolveAndMutate/walkMessageas appropriate), not just logging the gap.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/references/reference_validator.go` around lines 199 - 217, Update ReferenceValidator.walkMessage to validate message-valued map entries instead of returning after the warning. Iterate val.Map().Range, recurse through the existing resolveAndMutate/walkMessage flow for each message value, propagate any validation error through internalErr, and preserve the current behavior for non-message map values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@internal/references/reference_validator.go`:
- Around line 199-217: Update ReferenceValidator.walkMessage to validate
message-valued map entries instead of returning after the warning. Iterate
val.Map().Range, recurse through the existing resolveAndMutate/walkMessage flow
for each message value, propagate any validation error through internalErr, and
preserve the current behavior for non-message map values.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: a9566091-57b3-4e14-b516-8444d7cf6d19
📒 Files selected for processing (2)
internal/references/reference_validator.gointernal/references/reference_validator_test.go
danielerez
left a comment
There was a problem hiding this comment.
Looks good, just a couple of comments.
Assisted-by: Claude Code <noreply@anthropic.com> Signed-off-by: Haim Tayrie <htayrie@htayrie-thinkpadt14gen5.raanaii.csb>
Add a gRPC unary server interceptor that validates resource references in Create/Update requests using protoreflect. The interceptor discovers reference-typed fields by naming convention (*Reference, *LocalReference), validates them against registered lookup functions, auto-populates missing id/name fields, and returns aggregated InvalidArgument errors with structured BadRequest FieldViolation details. Key behaviors: - Fail-closed: unregistered reference types produce Internal error - Tenant context: local refs use owning resource's metadata; full refs support explicit project and shared flag - Three resolution modes: name-only, id-only, both-provided (mismatch check) - Prometheus metrics: osac_reference_validation_total (counter), osac_reference_validation_duration_seconds (histogram) - Structured logging at DEBUG/WARN/ERROR levels The interceptor is registered at the end of the gRPC chain (after JIT provisioning). No lookup functions are registered yet — the interceptor is a no-op until the networking chunk (OSAC-3093) adds registrations. Assisted-by: Claude Code <noreply@anthropic.com> Signed-off-by: Haim Tayrie <htayrie@htayrie-thinkpadt14gen5.raanaii.csb>
Extract registerOrReuse generic helper to avoid assigning nil to err that is immediately overwritten by the next Register call. Assisted-by: Claude Code <noreply@anthropic.com> Signed-off-by: Haim Tayrie <htayrie@htayrie-thinkpadt14gen5.raanaii.csb>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@internal/references/reference_validator.go`:
- Around line 134-144: Harden the registry access used by
ReferenceValidator.Register and resolveAndMutate so sealing cannot race with map
reads or writes. Prefer making the registry immutable before UnaryServer seals
it, or protect publication and access with a synchronized/atomic replacement
mechanism; retain the late-Register rejection while ensuring no concurrent map
access occurs.
- Around line 294-301: Update the field validation in the reference validation
flow around idField and nameField to also require both fields to use the string
kind, not merely be present. Return the existing Internal error response with a
clear required-string-fields message when either kind is invalid, while
preserving the subsequent Get and Set behavior for valid reference types.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 2ff4f329-97f7-4fb8-a7d4-58887e981d44
⛔ Files ignored due to path filters (2)
internal/api/osac/tests/v1/reference_test_types.pb.gois excluded by!**/*.pb.gointernal/api/osac/tests/v1/reference_test_types_protoopaque.pb.gois excluded by!**/*.pb.go
📒 Files selected for processing (6)
go.modinternal/cmd/service/start/grpcserver/start_grpc_server_cmd.gointernal/references/reference_validator.gointernal/references/reference_validator_test.gointernal/references/references_suite_test.goproto/tests/osac/tests/v1/reference_test_types.proto
Check that id and name fields are StringKind via isStringField helper, not just present. Prevents a panic from ValueOfString on a non-string field. Assisted-by: Claude Code <noreply@anthropic.com> Signed-off-by: Haim Tayrie <htayrie@htayrie-thinkpadt14gen5.raanaii.csb>
|
/lgtm |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: htayrie-rh, rccrdpccl The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
9ffc025
into
osac-project:main
…gories Replace raw string reference fields with typed protobuf reference messages for all inter-resource references. This enables the reference validation interceptor (merged in osac-project#963) to validate, resolve, and auto-populate reference fields on Create/Update requests. Changes: - Define Full Reference and Local Reference message types for ~20 resources - Register DAO-backed lookup functions for all reference types - Update server code to use typed reference getters and CEL nested paths - Migration 87: backfill string refs to objects, drop Z0002 forward-ref triggers (interceptor replaces them), update Z0003 reverse-ref triggers with nested JSON paths - Update CLI commands to construct reference messages - Fix all test fixtures for typed reference assertions Covers epics OSAC-3083 through OSAC-3087 (14 DEV tasks). Assisted-by: Claude Code <noreply@anthropic.com> Signed-off-by: Haim Tayrie <htayrie@htayrie-thinkpadt14gen5.raanaii.csb>
…gories Replace raw string reference fields with typed protobuf reference messages for all inter-resource references. This enables the reference validation interceptor (merged in osac-project#963) to validate, resolve, and auto-populate reference fields on Create/Update requests. Changes: - Define Full Reference and Local Reference message types for ~20 resources - Register DAO-backed lookup functions for all reference types - Update server code to use typed reference getters and CEL nested paths - Migration 87: backfill string refs to objects, drop Z0002 forward-ref triggers (interceptor replaces them), update Z0003 reverse-ref triggers with nested JSON paths - Update CLI commands to construct reference messages - Fix all test fixtures for typed reference assertions Covers epics OSAC-3083 through OSAC-3087 (14 DEV tasks). Assisted-by: Claude Code <noreply@anthropic.com> Signed-off-by: Haim Tayrie <htayrie@htayrie-thinkpadt14gen5.raanaii.csb>
…gories Replace raw string reference fields with typed protobuf reference messages for all inter-resource references. This enables the reference validation interceptor (merged in osac-project#963) to validate, resolve, and auto-populate reference fields on Create/Update requests. Changes: - Define Full Reference and Local Reference message types for ~20 resources - Register DAO-backed lookup functions for all reference types - Update server code to use typed reference getters and CEL nested paths - Migration 87: backfill string refs to objects, drop Z0002 forward-ref triggers (interceptor replaces them), update Z0003 reverse-ref triggers with nested JSON paths - Update CLI commands to construct reference messages - Fix all test fixtures for typed reference assertions Covers epics OSAC-3083 through OSAC-3087 (14 DEV tasks). Assisted-by: Claude Code <noreply@anthropic.com> Signed-off-by: Haim Tayrie <htayrie@htayrie-thinkpadt14gen5.raanaii.csb>
…gories Replace raw string reference fields with typed protobuf reference messages for all inter-resource references. This enables the reference validation interceptor (merged in osac-project#963) to validate, resolve, and auto-populate reference fields on Create/Update requests. Changes: - Define Full Reference and Local Reference message types for ~20 resources - Register DAO-backed lookup functions for all reference types - Update server code to use typed reference getters and CEL nested paths - Migration 87: backfill string refs to objects, drop Z0002 forward-ref triggers (interceptor replaces them), update Z0003 reverse-ref triggers with nested JSON paths - Update CLI commands to construct reference messages - Fix all test fixtures for typed reference assertions Covers epics OSAC-3083 through OSAC-3087 (14 DEV tasks). Assisted-by: Claude Code <noreply@anthropic.com> Signed-off-by: Haim Tayrie <htayrie@htayrie-thinkpadt14gen5.raanaii.csb>
…gories Replace raw string reference fields with typed protobuf reference messages for all inter-resource references. This enables the reference validation interceptor (merged in osac-project#963) to validate, resolve, and auto-populate reference fields on Create/Update requests. Changes: - Define Full Reference and Local Reference message types for ~20 resources - Register DAO-backed lookup functions for all reference types - Update server code to use typed reference getters and CEL nested paths - Migration 87: backfill string refs to objects, drop Z0002 forward-ref triggers (interceptor replaces them), update Z0003 reverse-ref triggers with nested JSON paths - Update CLI commands to construct reference messages - Fix all test fixtures for typed reference assertions Covers epics OSAC-3083 through OSAC-3087 (14 DEV tasks). Assisted-by: Claude Code <noreply@anthropic.com> Signed-off-by: Haim Tayrie <htayrie@htayrie-thinkpadt14gen5.raanaii.csb>
…gories Replace raw string reference fields with typed protobuf reference messages for all inter-resource references. This enables the reference validation interceptor (merged in osac-project#963) to validate, resolve, and auto-populate reference fields on Create/Update requests. Changes: - Define Full Reference and Local Reference message types for ~20 resources - Register DAO-backed lookup functions for all reference types - Update server code to use typed reference getters and CEL nested paths - Migration 87: backfill string refs to objects, drop Z0002 forward-ref triggers (interceptor replaces them), update Z0003 reverse-ref triggers with nested JSON paths - Update CLI commands to construct reference messages - Fix all test fixtures for typed reference assertions Covers epics OSAC-3083 through OSAC-3087 (14 DEV tasks). Assisted-by: Claude Code <noreply@anthropic.com> Signed-off-by: Haim Tayrie <htayrie@htayrie-thinkpadt14gen5.raanaii.csb>
OSAC-3082: Implement reference validation interceptor
Jira: OSAC-3082
Story type: [DEV]
Summary
Implements a centralized gRPC unary server interceptor that validates resource references in Create and Update requests using protoreflect. The interceptor discovers reference-typed fields by naming convention (
*Reference,*LocalReference), validates referenced resources exist via registered lookup functions, auto-populates missing id/name fields, and returns aggregatedInvalidArgumenterrors with structuredBadRequestFieldViolationdetails.This is the foundation for OSAC-1330 (type-safe resource references). The interceptor is registered in the gRPC chain but has no lookup functions yet — it becomes active when subsequent epics (Networking, Compute, IP Management) register their reference types.
Changes
New package:
internal/references/ReferenceValidatorinterceptor with builder pattern (NewReferenceValidator().SetLogger().SetMetricsRegisterer().Build())Internalerrorosac_reference_validation_total(CounterVec) andosac_reference_validation_duration_seconds(HistogramVec)Interceptor chain registration
Test proto definitions
proto/tests/osac/tests/v1/reference_test_types.protowith 7 message types and 3 request types covering all reference field patternsTesting
Acceptance Criteria
InvalidArgumentwithBadRequestcontainingFieldViolationentries with field pathsosac_reference_validation_total,osac_reference_validation_duration_seconds)Summary by CodeRabbit
InvalidArgumenterrors.