Skip to content

Commit

Permalink
Fix Rule Evaluation Logic for Handling Multiple Rules of the Same Typ…
Browse files Browse the repository at this point in the history
…e - Part 1 (No Migrations)

* Introduced a new 'name' field for rules, which is mandatory when having different rules of the same type under one entity

* Existing names can be overridden by peforming a `profile apply` to use sensible rule names

* If no rule name is specified, and the profile is compliant i.e. rule type not repeated, rule-type is used as the default rule name

Signed-off-by: Vyom-Yadav <[email protected]>
  • Loading branch information
Vyom-Yadav committed Jan 23, 2024
1 parent af30b40 commit fb78963
Show file tree
Hide file tree
Showing 15 changed files with 1,218 additions and 531 deletions.
15 changes: 9 additions & 6 deletions cmd/cli/app/profile/status/status_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ func listCommand(ctx context.Context, cmd *cobra.Command, conn *grpc.ClientConn)
profileName := viper.GetString("name")
format := viper.GetString("output")
all := viper.GetBool("detailed")
rule := viper.GetString("rule")
ruleType := viper.GetString("ruleType")
ruleName := viper.GetString("ruleName")

// Ensure provider is supported
if !app.IsProviderSupported(provider) {
Expand All @@ -59,10 +60,11 @@ func listCommand(ctx context.Context, cmd *cobra.Command, conn *grpc.ClientConn)
}

resp, err := client.GetProfileStatusByName(ctx, &minderv1.GetProfileStatusByNameRequest{
Context: &minderv1.Context{Provider: &provider, Project: &project},
Name: profileName,
All: all,
Rule: rule,
Context: &minderv1.Context{Provider: &provider, Project: &project},
Name: profileName,
All: all,
RuleType: ruleType,
RuleName: ruleName,
})
if err != nil {
return cli.MessageAndError("Error getting profile status", err)
Expand Down Expand Up @@ -98,5 +100,6 @@ func init() {
profileStatusCmd.AddCommand(listCmd)
// Flags
listCmd.Flags().BoolP("detailed", "d", false, "List all profile violations")
listCmd.Flags().StringP("rule", "r", "", "Filter profile status list by rule")
listCmd.Flags().StringP("ruleType", "r", "", "Filter profile status list by rule type")
listCmd.Flags().String("ruleName", "", "Filter profile status list by rule name")
}
2 changes: 1 addition & 1 deletion cmd/cli/app/profile/table_render.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ func RenderRuleEvaluationStatusTable(
for _, eval := range statuses {
t.AddRowWithColor(
layouts.NoColor(eval.RuleId),
layouts.NoColor(eval.RuleName),
layouts.NoColor(eval.RuleDescriptionName),
layouts.NoColor(eval.Entity),
getColoredEvalStatus(eval.Status),
getRemediateStatusColor(eval.RemediationStatus),
Expand Down
8 changes: 4 additions & 4 deletions database/mock/store.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion database/query/profile_status.sql
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,4 @@ WHERE res.profile_id = $1 AND
ELSE false
END
) AND (rt.name = sqlc.narg(rule_name) OR sqlc.narg(rule_name) IS NULL)
;
;
86 changes: 85 additions & 1 deletion docs/docs/how-to/create_profile.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ alert: "on"
remediate: "on"
repository:
- type: secret_scanning
name: "secret_scanning_github" # Optional, as there aren't multiple rules
# of the same type under the entity - repository
def:
enabled: true
```
Expand All @@ -250,4 +252,86 @@ filter the output using `jq`. For example, to get all rules that pertain to the
run the following command:
```bash
minder profile status list --name stacklok-remediate-profile -d -ojson 2>/dev/null | jq -C '.ruleEvaluationStatus | map(select(.entityInfo.repo_name == "minder" and .status == "failure"))'
```
```

## Defining Rule Names in Profiles

In Minder profiles, rules are identified by their type and, optionally, a unique name.

### Rule Types vs Rule Names

Rule types are mandatory and refer to the kind of rule being applied. Rule names, on the other hand, are optional
identifiers that become crucial when multiple rules of the same type exist under an entity.

```yaml
repository:
- type: secret_scanning
name: "secret_scanning_github"
def:
enabled: true
```
In this example, `secret_scanning` is the rule type and `secret_scanning_github` is the rule name.

### When are Rule Names Mandatory?

If you're using multiple rules of the same type under an entity, each rule must have a unique name. This helps
distinguish between rules and understand their specific purpose.

```yaml
repository:
- type: secret_scanning
name: "secret_scanning_github"
def:
enabled: true
- type: secret_scanning
name: "secret_scanning_github_2"
def:
enabled: false
```
Here, we have two rules of the same type `secret_scanning` under the `repository` entity. Each rule has a unique name.

### Uniqueness of Rule Names

No two rules, whether of the same type or different types, can have the same name under an entity. This avoids
confusion and ensures each rule can be individually managed.

```yaml
repository: # Would return an error while creating
- type: secret_scanning
name: "protect_github"
def:
enabled: true
- type: secret_push_protection
name: "protect_github"
def:
enabled: false
```
In this example, even though the rules are of different types (`secret_scanning` and `secret_push_protection`),
Minder will return an error while creating this profile as rule names are same under the same entity.
You may use same rule names under different entities (repository, artifacts, etc.)

Also, a rule's `type` and `name` should not be identical.

### Example

Consider a profile with two `dependabot_configured` rules under the `repository` entity. The first rule has a unique
name, "Dependabot Configured for GoLang". The second rule doesn't have a name, which is acceptable as Minder would
internally use the rule type as the name for the rule.

```yaml
repository:
- type: dependabot_configured
name: "Dependabot Configured for GoLang"
def:
package_ecosystem: gomod
schedule_interval: daily
apply_if_file: go.mod
- type: dependabot_configured # internally 'name' would be 'dependabot_configured'
def:
package_ecosystem: npm
schedule_interval: daily
apply_if_file: docs/package.json
```

You can find the rule definitions used above and many profile examples at
[minder-rules-and-profiles](https://github.com/stacklok/minder-rules-and-profiles) repository.
7 changes: 5 additions & 2 deletions docs/docs/ref/proto.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit fb78963

Please sign in to comment.