-
-
Notifications
You must be signed in to change notification settings - Fork 36
/
generate_ruleset.go
112 lines (89 loc) · 3.18 KB
/
generate_ruleset.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Copyright 2022 Dave Shanley / Quobix
// SPDX-License-Identifier: MIT
package cmd
import (
"encoding/json"
"errors"
"fmt"
"github.com/daveshanley/vacuum/rulesets"
"github.com/pterm/pterm"
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
"os"
)
func GetGenerateRulesetCommand() *cobra.Command {
cmd := &cobra.Command{
SilenceUsage: true,
SilenceErrors: true,
Use: "generate-ruleset",
Short: "Generate a vacuum RuleSet",
Long: "Generate a YAML ruleset containing 'all', or 'recommended' rules",
Example: "vacuum generate-ruleset recommended | all <ruleset-output-name>",
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
switch len(args) {
case 0:
return []string{"recommended", "all"}, cobra.ShellCompDirectiveNoFileComp
case 1:
return []string{"yaml", "yml"}, cobra.ShellCompDirectiveFilterFileExt
default:
return nil, cobra.ShellCompDirectiveNoFileComp
}
},
RunE: func(cmd *cobra.Command, args []string) error {
PrintBanner()
// check for file args
if len(args) < 1 {
errText := "please supply 'recommended', 'owasp' or 'all' and a file path to output the ruleset"
pterm.Error.Println(errText)
pterm.Println()
return errors.New(errText)
}
if args[0] != "recommended" && args[0] != "all" && args[0] != "owasp" {
errText := fmt.Sprintf("please use 'all', 'owasp' or 'recommended' your choice '%s' is not valid", args[0])
pterm.Error.Println(errText)
pterm.Println()
return errors.New(errText)
}
extension := ".yaml"
reportOutput := "ruleset"
if len(args) == 2 {
reportOutput = args[1]
}
// read spec and parse to dashboard.
defaultRuleSets := rulesets.BuildDefaultRuleSets()
var selectedRuleSet *rulesets.RuleSet
// default is recommended rules, based on spectral (for now anyway)
selectedRuleSet = defaultRuleSets.GenerateOpenAPIRecommendedRuleSet()
if args[0] == "all" {
selectedRuleSet = defaultRuleSets.GenerateOpenAPIDefaultRuleSet()
}
if args[0] == "owasp" {
selectedRuleSet = rulesets.GenerateOWASPOpenAPIRuleSet()
}
// this bit needs a re-think, but it works for now.
// because Spectral has an ass backwards schema design, this disco dance here
// is to re-encode from rules to ruleDefinitions (which is a proxy property)
encoded, _ := json.Marshal(selectedRuleSet.Rules)
encodedMap := make(map[string]interface{})
err := json.Unmarshal(encoded, &encodedMap)
if err != nil {
return err
}
selectedRuleSet.RuleDefinitions = encodedMap
pterm.Info.Printf("Generating RuleSet rules: %s", selectedRuleSet.DocumentationURI)
pterm.Println()
yamlBytes, _ := yaml.Marshal(selectedRuleSet)
reportOutputName := fmt.Sprintf("%s-%s%s", reportOutput, args[0], extension)
err = os.WriteFile(reportOutputName, yamlBytes, 0664)
if err != nil {
pterm.Error.Printf("Unable to write RuleSet file: '%s': %s\n", reportOutputName, err.Error())
pterm.Println()
return err
}
pterm.Success.Printf("RuleSet generated for '%s', written to '%s'\n", args[0], reportOutputName)
pterm.Println()
return nil
},
}
return cmd
}