Skip to content

Commit b50e41e

Browse files
committed
Flag-protect new functionality
1 parent ed1cb1d commit b50e41e

File tree

15 files changed

+146
-55
lines changed

15 files changed

+146
-55
lines changed

cmd/dev/app/rule_type/rttst.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ func testCmdRun(cmd *cobra.Command, _ []string) error {
197197

198198
// TODO: use cobra context here
199199
ctx := context.Background()
200-
eng, err := rtengine.NewRuleTypeEngine(ctx, ruletype, prov, options.WithDataSources(dsRegistry))
200+
eng, err := rtengine.NewRuleTypeEngine(ctx, ruletype, prov, nil /*experiments*/, options.WithDataSources(dsRegistry))
201201
if err != nil {
202202
return fmt.Errorf("cannot create rule type engine: %w", err)
203203
}

internal/controlplane/handlers_ruletype.go

+29-11
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414

1515
"github.com/google/uuid"
1616
"github.com/microcosm-cc/bluemonday"
17+
"github.com/open-feature/go-sdk/openfeature"
1718
"github.com/yuin/goldmark"
1819
"github.com/yuin/goldmark/extension"
1920
"github.com/yuin/goldmark/parser"
@@ -23,6 +24,7 @@ import (
2324

2425
"github.com/mindersec/minder/internal/db"
2526
"github.com/mindersec/minder/internal/engine/engcontext"
27+
"github.com/mindersec/minder/internal/engine/ingester/git"
2628
"github.com/mindersec/minder/internal/flags"
2729
"github.com/mindersec/minder/internal/logger"
2830
"github.com/mindersec/minder/internal/util"
@@ -175,14 +177,9 @@ func (s *Server) CreateRuleType(
175177
return nil, util.UserVisibleError(codes.InvalidArgument, "%s", err)
176178
}
177179

178-
ruleDS := crt.GetRuleType().GetDef().GetEval().GetDataSources()
179-
if len(ruleDS) > 0 && !flags.Bool(ctx, s.featureFlags, flags.DataSources) {
180-
return nil, util.UserVisibleError(codes.InvalidArgument, "DataSources feature is disabled")
181-
}
182-
183-
prCommentAlert := crt.GetRuleType().GetDef().GetAlert().GetPullRequestComment()
184-
if prCommentAlert != nil && !flags.Bool(ctx, s.featureFlags, flags.PRCommentAlert) {
185-
return nil, util.UserVisibleError(codes.InvalidArgument, "Pull request comment alert type is disabled")
180+
ruleDef := crt.GetRuleType().GetDef()
181+
if err := checkRuleDefinitionFlags(ctx, s.featureFlags, ruleDef); err != nil {
182+
return nil, err
186183
}
187184

188185
newRuleType, err := db.WithTransaction(s.store, func(qtx db.ExtendQuerier) (*minderv1.RuleType, error) {
@@ -204,6 +201,27 @@ func (s *Server) CreateRuleType(
204201
}, nil
205202
}
206203

204+
func checkRuleDefinitionFlags(
205+
ctx context.Context, featureFlags openfeature.IClient, ruleDef *minderv1.RuleType_Definition) *util.NiceStatus {
206+
ruleDS := ruleDef.GetEval().GetDataSources()
207+
if len(ruleDS) > 0 && !flags.Bool(ctx, featureFlags, flags.DataSources) {
208+
return util.UserVisibleError(codes.InvalidArgument, "DataSources feature is disabled")
209+
}
210+
211+
prCommentAlert := ruleDef.GetAlert().GetPullRequestComment()
212+
if prCommentAlert != nil && !flags.Bool(ctx, featureFlags, flags.PRCommentAlert) {
213+
return util.UserVisibleError(codes.InvalidArgument, "Pull request comment alert type is disabled")
214+
}
215+
216+
usesGitPR := ruleDef.GetIngest().GetType() == git.GitRuleDataIngestType &&
217+
ruleDef.GetInEntity() == minderv1.PullRequestEntity.String()
218+
if usesGitPR && !flags.Bool(ctx, featureFlags, flags.GitPRDiffs) {
219+
return util.UserVisibleError(codes.InvalidArgument, "Git pull request ingest is disabled")
220+
}
221+
222+
return nil
223+
}
224+
207225
// UpdateRuleType is a method to update a rule type
208226
func (s *Server) UpdateRuleType(
209227
ctx context.Context,
@@ -227,9 +245,9 @@ func (s *Server) UpdateRuleType(
227245
return nil, util.UserVisibleError(codes.InvalidArgument, "%s", err)
228246
}
229247

230-
ruleDS := urt.GetRuleType().GetDef().GetEval().GetDataSources()
231-
if len(ruleDS) > 0 && !flags.Bool(ctx, s.featureFlags, flags.DataSources) {
232-
return nil, util.UserVisibleError(codes.InvalidArgument, "DataSources feature is disabled")
248+
ruleDef := urt.GetRuleType().GetDef()
249+
if err := checkRuleDefinitionFlags(ctx, s.featureFlags, ruleDef); err != nil {
250+
return nil, err
233251
}
234252

235253
updatedRuleType, err := db.WithTransaction(s.store, func(qtx db.ExtendQuerier) (*minderv1.RuleType, error) {

internal/engine/eval/eval.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ import (
1919
minderv1 "github.com/mindersec/minder/pkg/api/protobuf/go/minder/v1"
2020
"github.com/mindersec/minder/pkg/engine/v1/interfaces"
2121
provinfv1 "github.com/mindersec/minder/pkg/providers/v1"
22+
"github.com/open-feature/go-sdk/openfeature"
2223
)
2324

2425
// NewRuleEvaluator creates a new rule data evaluator
2526
func NewRuleEvaluator(
2627
ctx context.Context,
2728
ruletype *minderv1.RuleType,
2829
provider provinfv1.Provider,
30+
featureFlags openfeature.IClient,
2931
opts ...eoptions.Option,
3032
) (interfaces.Evaluator, error) {
3133
e := ruletype.Def.GetEval()
@@ -41,7 +43,7 @@ func NewRuleEvaluator(
4143
}
4244
return jq.NewJQEvaluator(e.GetJq(), opts...)
4345
case rego.RegoEvalType:
44-
return rego.NewRegoEvaluator(e.GetRego(), opts...)
46+
return rego.NewRegoEvaluator(e.GetRego(), featureFlags, opts...)
4547
case vulncheck.VulncheckEvalType:
4648
client, err := provinfv1.As[provinfv1.GitHub](provider)
4749
if err != nil {

internal/engine/eval/eval_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func TestNewRuleEvaluatorWorks(t *testing.T) {
7171
t.Run(tt.name, func(t *testing.T) {
7272
t.Parallel()
7373

74-
got, err := eval.NewRuleEvaluator(context.Background(), tt.args.rt, nil)
74+
got, err := eval.NewRuleEvaluator(context.Background(), tt.args.rt, nil, nil)
7575
assert.NoError(t, err, "unexpected error")
7676
assert.NotNil(t, got, "unexpected nil")
7777
})
@@ -146,7 +146,7 @@ func TestNewRuleEvaluatorFails(t *testing.T) {
146146
t.Run(tt.name, func(t *testing.T) {
147147
t.Parallel()
148148

149-
got, err := eval.NewRuleEvaluator(context.Background(), tt.args.rt, nil)
149+
got, err := eval.NewRuleEvaluator(context.Background(), tt.args.rt, nil, nil)
150150
assert.Error(t, err, "should have errored")
151151
assert.Nil(t, got, "should be nil")
152152
})

internal/engine/eval/rego/eval.go

+11-7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"fmt"
1010
"os"
1111

12+
"github.com/open-feature/go-sdk/openfeature"
1213
"github.com/open-policy-agent/opa/rego"
1314
"github.com/open-policy-agent/opa/topdown/print"
1415
"google.golang.org/protobuf/reflect/protoreflect"
@@ -37,10 +38,11 @@ const (
3738
// It initializes the rego engine and evaluates the rules
3839
// The default rego package is "minder"
3940
type Evaluator struct {
40-
cfg *Config
41-
regoOpts []func(*rego.Rego)
42-
reseval resultEvaluator
43-
datasources *v1datasources.DataSourceRegistry
41+
cfg *Config
42+
featureFlags openfeature.IClient
43+
regoOpts []func(*rego.Rego)
44+
reseval resultEvaluator
45+
datasources *v1datasources.DataSourceRegistry
4446
}
4547

4648
// Input is the input for the rego evaluator
@@ -66,6 +68,7 @@ var _ print.Hook = (*hook)(nil)
6668
// NewRegoEvaluator creates a new rego evaluator
6769
func NewRegoEvaluator(
6870
cfg *minderv1.RuleType_Definition_Eval_Rego,
71+
featureFlags openfeature.IClient,
6972
opts ...eoptions.Option,
7073
) (*Evaluator, error) {
7174
c, err := parseConfig(cfg)
@@ -76,8 +79,9 @@ func NewRegoEvaluator(
7679
re := c.getEvalType()
7780

7881
eval := &Evaluator{
79-
cfg: c,
80-
reseval: re,
82+
cfg: c,
83+
featureFlags: featureFlags,
84+
reseval: re,
8185
regoOpts: []func(*rego.Rego){
8286
re.getQuery(),
8387
rego.Module(MinderRegoFile, c.Def),
@@ -119,7 +123,7 @@ func (e *Evaluator) Eval(
119123
regoFuncOptions := []func(*rego.Rego){}
120124

121125
// Initialize the built-in minder library rego functions
122-
regoFuncOptions = append(regoFuncOptions, instantiateRegoLib(res)...)
126+
regoFuncOptions = append(regoFuncOptions, instantiateRegoLib(ctx, e.featureFlags, res)...)
123127

124128
// If the evaluator has data sources defined, expose their functions
125129
regoFuncOptions = append(regoFuncOptions, buildDataSourceOptions(res, e.datasources)...)

internal/engine/eval/rego/fuzz_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ func FuzzRegoEval(f *testing.F) {
2020
Type: ConstraintsEvaluationType.String(),
2121
Def: policy,
2222
},
23+
nil,
2324
)
2425
if err != nil {
2526
return

internal/engine/eval/rego/lib.go

+23-10
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ import (
1919

2020
"github.com/go-git/go-billy/v5"
2121
billyutil "github.com/go-git/go-billy/v5/util"
22+
"github.com/open-feature/go-sdk/openfeature"
2223
"github.com/open-policy-agent/opa/ast"
2324
"github.com/open-policy-agent/opa/rego"
2425
"github.com/open-policy-agent/opa/types"
2526
"github.com/stacklok/frizbee/pkg/replacer"
2627
"github.com/stacklok/frizbee/pkg/utils/config"
2728
"gopkg.in/yaml.v3"
2829

30+
"github.com/mindersec/minder/internal/flags"
2931
"github.com/mindersec/minder/internal/util"
3032
"github.com/mindersec/minder/pkg/engine/v1/interfaces"
3133
)
@@ -38,25 +40,36 @@ var MinderRegoLib = []func(res *interfaces.Result) func(*rego.Rego){
3840
FileHTTPType,
3941
FileRead,
4042
FileWalk,
41-
FileArchive,
4243
ListGithubActions,
43-
BaseFileExists,
44-
BaseFileLs,
45-
BaseFileLsGlob,
46-
BaseFileHTTPType,
47-
BaseFileRead,
48-
BaseFileWalk,
49-
BaseListGithubActions,
50-
BaseFileArchive,
5144
ParseYaml,
5245
JQIsTrue,
5346
}
5447

55-
func instantiateRegoLib(res *interfaces.Result) []func(*rego.Rego) {
48+
var MinderRegoLibExperiments = map[flags.Experiment][]func(res *interfaces.Result) func(*rego.Rego){
49+
flags.TarGzFunctions: {FileArchive, BaseFileArchive},
50+
flags.GitPRDiffs: {
51+
BaseFileExists,
52+
BaseFileLs,
53+
BaseFileLsGlob,
54+
BaseFileHTTPType,
55+
BaseFileRead,
56+
BaseFileWalk,
57+
BaseListGithubActions,
58+
},
59+
}
60+
61+
func instantiateRegoLib(ctx context.Context, featureFlags openfeature.IClient, res *interfaces.Result) []func(*rego.Rego) {
5662
var lib []func(*rego.Rego)
5763
for _, f := range MinderRegoLib {
5864
lib = append(lib, f(res))
5965
}
66+
for flag, funcs := range MinderRegoLibExperiments {
67+
if flags.Bool(ctx, featureFlags, flag) {
68+
for _, f := range funcs {
69+
lib = append(lib, f(res))
70+
}
71+
}
72+
}
6073
return lib
6174
}
6275

0 commit comments

Comments
 (0)