Add provider_trait field to RuleType.Definition - #6669
Conversation
6f0b4b8 to
417f0a0
Compare
|
seems there are linter and unit test issues to solve |
| minderv1 "github.com/mindersec/minder/pkg/api/protobuf/go/minder/v1" | ||
| "github.com/mindersec/minder/pkg/engine/selectors" | ||
| "github.com/mindersec/minder/pkg/ruletypes" | ||
| "github.com/mindersec/minder/internal/providers" |
There was a problem hiding this comment.
The internal/providers import needs to be placed above the pkg/ imports in this block. gci expects module-local internal/ packages to come before pkg/ packages, alphabetically, and the current ordering is what's tripping up the lint CI check. Moving it up should be a one-line fix.
krrish175-byte
left a comment
There was a problem hiding this comment.
The design here is genuinely well thought out. Reusing the existing ProviderType/CanImplement vocabulary instead of spinning up a new capability abstraction is the right call, and doing the check up front at profile validation time (matching the in_entity pattern) is much cleaner than reaching for ErrEvaluationSkipped. The test coverage covers the meaningful cases.
One thing blocking merge right now: the internal/providers import in validator.go is in the wrong group, which is causing the gci lint failure in CI. Left an inline comment with details. It's a one-line fix.
Separately, the unit test failure in TestHandleGitHubWebHook/create ("no event received after waiting 10ms") is in a completely different package and looks like a pre-existing flaky test rather than a regression from this PR. Worth getting a clean re-run after fixing the import to confirm nothing else is red.
evankanderson
left a comment
There was a problem hiding this comment.
This is a good start, but a couple comments for when you're back from break.
| // evaluate this rule type. If PROVIDER_TYPE_UNSPECIFIED (the | ||
| // zero value / default), the rule type is not gated by | ||
| // provider trait. | ||
| ProviderType provider_trait = 8; |
There was a problem hiding this comment.
Given the presence of datasources which allow pulling from additional APIs (e.g. git and github or git and gitlab), let's make this a list -- see my last comments on #6651 for a couple examples that check both repo contents and forge-specific APIs.
| if trait := ruleTypePB.Def.ProviderTrait; trait != minderv1.ProviderType_PROVIDER_TYPE_UNSPECIFIED { | ||
| dbTraits, err := providers.PBProviderTypesToDB([]minderv1.ProviderType{trait}) | ||
| if err != nil { | ||
| return fmt.Errorf("invalid provider_trait on rule type %s: %w", ruleTypePB.Name, err) | ||
| } | ||
|
|
||
| satisfied := false | ||
| for _, p := range dbProviders { | ||
| if p.CanImplement(dbTraits[0]) { | ||
| satisfied = true | ||
| break | ||
| } | ||
| } | ||
|
|
||
| if !satisfied { | ||
| return &RuleValidationError{ | ||
| Err: fmt.Sprintf( | ||
| "rule type %s requires provider trait %s, but no provider in this project implements it", | ||
| ruleTypePB.Name, trait.String()), | ||
| RuleType: ruleTypePB.Name, | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
I'm not sure we want to block ruletype creation / management based on the set of currently-registered providers.
Two concerns about this semantic:
- It prevents loading a set of ruletypes first into an empty-ish project, then adding resources to be managed by those ruletypes. I'm not sure how common this is, but I can certainly imagine it for both automated testing and consulting-type roles.
- As implemented, this protection is incomplete -- if the provider is later un-registered, the ruletype (and any profiles including it) will still remain. Unwinding that pile of policy seems surprising, so I'd probably steer away from the semantic that "you must currently have providers registered matching a ruletype's
provider_traitsto manage that ruletype".
I think a warning when editing a profile could be appropriate, but you'd need to add a bunch of plumbing to support collecting and returning warnings in addition to the rule execution (unlike errors, which can early-return in many cases).
There was a problem hiding this comment.
With that said, I think we do want a validation that the provider_traits are in the set registered by Minder.
This should happen when the ruletype is created or updated, not when it is added to a profile.
|
Thanks both — makes sense on all counts. @krrish175-byte the import ordering is fixed locally (gci), will push once I'm back. @evankanderson agreed on both:
I'm on a break this week so will push the rework once I'm back — wanted to confirm I've got the plan right before I dig in. Will follow up on #6651 too. |
Summary
Adds a
provider_traitfield toRuleType.Definition, letting a rule type declare an API/interface requirement (e.g.github,git,oci) rather than being pinned to a specific named provider registration. This reuses the existingProviderType/CanImplementtrait vocabulary already used elsewhere in the provider system, instead of introducing anew capability abstraction.
This is currently blocking
osps-ac-03-02(branch deletion protection), since GitHub and GitLab branch-protection semantics/APIs differ enough that a single generic rule type can't cleanly cover both. This PR lays the schema + validation groundwork; applying it to unblockosps-ac-03-02is a separate follow-up inminder-rules-and-profiles.Changes
provider_trait(ProviderType, field 8) toRuleType.Definitionin the proto, and regenerated bindings (pkg/api/protobuf/go/minder/v1/minder.pb.go,pkg/api/openapi/minder/v1/minder.swagger.json,docs/docs/ref/proto.mdx).pkg/profiles/validator.go'svalidateEntities,usingqtx.ListProvidersByProjectID+db.Provider.CanImplementto check whether any provider in the project satisfies the rule type's declared trait. This follows the same static, up-front pattern as the existingin_entitycheck, rather than the noisierErrEvaluationSkippedper-entity skip path used by profile selectors.github/vsgitlab/inminder-rules-and-profiles) where the APIs genuinely diverge.Testing
Added unit tests in
pkg/profiles/validator_test.gocovering:provider_traitis satisfied by a provider in the project → validation passes.provider_trait) continue to pass unmodified, confirming the default (PROVIDER_TYPE_UNSPECIFIED) is not gated.Ran:
go build ./pkg/profiles/...andgo test ./pkg/profiles/... -run TestValidatorScenarios -v— all 16 scenarios pass.Scope
This covers schema + validation + tests only. Follow-ups:
provider_traittoosps-ac-03-02Part of #6650, closes #6651