Skip to content

Commit 73689df

Browse files
fix: refactor validate command to use configkit fields
1 parent ab63899 commit 73689df

File tree

3 files changed

+120
-83
lines changed

3 files changed

+120
-83
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.7.0] - 2024-05-17
9+
10+
### Changed
11+
12+
- Use ConfigKit with a metaconfig for all commands
13+
14+
### Added
15+
16+
- Gatecheck Config Encoder & Decoder
17+
818
## [0.6.2] - 2024-05-15
919

1020
### Changed

cmd/cli-config.go

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,21 @@ var (
1717
metadataActionInputName = "action_input_name"
1818
)
1919

20-
type Config struct {
21-
BundleTag string
22-
EPSSURL string
23-
KEVURL string
24-
}
25-
2620
type metaConfig struct {
2721
BundleTag configkit.MetaField
2822
EPSSURL configkit.MetaField
2923
KEVURL configkit.MetaField
3024
EPSSFilename configkit.MetaField
25+
KEVFilename configkit.MetaField
3126
Verbose configkit.MetaField
3227
Silent configkit.MetaField
28+
ConfigFilename configkit.MetaField
29+
Audit configkit.MetaField
3330
BundleTagValue []string
3431
bundleFile *os.File
3532
targetFile *os.File
3633
epssFile *os.File
34+
kevFile *os.File
3735
listSrcReader io.Reader
3836
listSrcName string
3937
listFormat string
@@ -106,11 +104,27 @@ var RuntimeConfig = metaConfig{
106104
cmd.Flags().StringVar(valueP, "epss-filename", "", usage)
107105
},
108106
Metadata: map[string]string{
109-
metadataFlagUsage: "the filename for a FIRST.org EPSS json file",
107+
metadataFlagUsage: "the filename for a FIRST.org EPSS csv file",
110108
metadataFieldType: "string",
111109
metadataActionInputName: "epss_filename",
112110
},
113111
},
112+
KEVFilename: configkit.MetaField{
113+
FieldName: "KEVFilename",
114+
EnvKey: "GATECHECK_EPSS_FILENAME",
115+
DefaultValue: "",
116+
FlagValueP: new(string),
117+
CobraSetupFunc: func(f configkit.MetaField, cmd *cobra.Command) {
118+
valueP := f.FlagValueP.(*string)
119+
usage := f.Metadata[metadataFlagUsage]
120+
cmd.Flags().StringVar(valueP, "kev-filename", "", usage)
121+
},
122+
Metadata: map[string]string{
123+
metadataFlagUsage: "the filename for a FIRST.org KEV json file",
124+
metadataFieldType: "string",
125+
metadataActionInputName: "kev_filename",
126+
},
127+
},
114128
Verbose: configkit.MetaField{
115129
FieldName: "Verbose",
116130
EnvKey: "GATECHECK_VERBOSE",
@@ -119,7 +133,7 @@ var RuntimeConfig = metaConfig{
119133
CobraSetupFunc: func(f configkit.MetaField, cmd *cobra.Command) {
120134
valueP := f.FlagValueP.(*bool)
121135
usage := f.Metadata[metadataFlagUsage]
122-
cmd.PersistentFlags().BoolVar(valueP, "verbose", false, usage)
136+
cmd.PersistentFlags().BoolVarP(valueP, "verbose", "v", false, usage)
123137
},
124138
Metadata: map[string]string{
125139
metadataFlagUsage: "log level set to debug",
@@ -143,4 +157,36 @@ var RuntimeConfig = metaConfig{
143157
metadataActionInputName: "silent",
144158
},
145159
},
160+
ConfigFilename: configkit.MetaField{
161+
FieldName: "ConfigFilename",
162+
EnvKey: "GATECHECK_CONFIG_FILENAME",
163+
DefaultValue: "",
164+
FlagValueP: new(string),
165+
CobraSetupFunc: func(f configkit.MetaField, cmd *cobra.Command) {
166+
valueP := f.FlagValueP.(*string)
167+
usage := f.Metadata[metadataFlagUsage]
168+
cmd.PersistentFlags().StringVarP(valueP, "file", "f", "", usage)
169+
},
170+
Metadata: map[string]string{
171+
metadataFlagUsage: "a validation configuration file",
172+
metadataFieldType: "string",
173+
metadataActionInputName: "config_filename",
174+
},
175+
},
176+
Audit: configkit.MetaField{
177+
FieldName: "Audit",
178+
EnvKey: "GATECHECK_AUDIT",
179+
DefaultValue: false,
180+
FlagValueP: new(bool),
181+
CobraSetupFunc: func(f configkit.MetaField, cmd *cobra.Command) {
182+
valueP := f.FlagValueP.(*bool)
183+
usage := f.Metadata[metadataFlagUsage]
184+
cmd.PersistentFlags().BoolVarP(valueP, "audit", "a", false, usage)
185+
},
186+
Metadata: map[string]string{
187+
metadataFlagUsage: "audit mode - will run all rules but wil always exit 0 for validation failures",
188+
metadataFieldType: "bool",
189+
metadataActionInputName: "audit",
190+
},
191+
},
146192
}

cmd/validate.go

Lines changed: 56 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -2,103 +2,84 @@ package cmd
22

33
import (
44
"fmt"
5-
"io"
65
"log/slog"
76
"os"
87

98
"github.com/gatecheckdev/gatecheck/pkg/gatecheck"
109
"github.com/spf13/cobra"
11-
"github.com/spf13/viper"
1210
)
1311

14-
func newValidateCommand() *cobra.Command {
15-
cmd := &cobra.Command{
16-
Use: "validate [FILE]",
17-
Short: "compare vulnerabilities to configured thresholds",
18-
Args: cobra.ExactArgs(1),
19-
RunE: runValidate,
20-
}
21-
22-
cmd.Flags().StringP("config", "f", "", "threshold configuration file")
23-
24-
cmd.Flags().String("epss-file", "", "use this file for epss scores, will not query API")
25-
_ = viper.BindPFlag("cli.validate.epss-file", cmd.Flags().Lookup("epss-file"))
26-
27-
cmd.Flags().String("kev-file", "", "use this file for kev catalog, will not query API")
28-
_ = viper.BindPFlag("cli.validate.kev-file", cmd.Flags().Lookup("kev-file"))
29-
30-
cmd.Flags().Bool("audit", false, "audit mode - will run all rules but wil always exit 0 for validation failures")
31-
_ = viper.BindPFlag("cli.validate.audit", cmd.Flags().Lookup("audit"))
32-
33-
return cmd
34-
}
35-
36-
// runValidate
37-
//
38-
// shell: gatecheck validate
39-
func runValidate(cmd *cobra.Command, args []string) error {
40-
configFilename, _ := cmd.Flags().GetString("config")
41-
targetFilename := args[0]
42-
43-
epssURL := viper.GetString("api.epss-url")
44-
kevURL := viper.GetString("api.kev-url")
45-
46-
epssFilename := viper.GetString("cli.validate.epss-file")
47-
kevFilename := viper.GetString("cli.validate.kev-file")
48-
49-
audit := viper.GetBool("cli.validate.audit")
12+
var validateCmd = &cobra.Command{
13+
Use: "validate [FILE]",
14+
Short: "compare vulnerabilities to configured thresholds",
15+
Args: cobra.ExactArgs(1),
16+
PreRunE: func(cmd *cobra.Command, args []string) error {
17+
configFilename := RuntimeConfig.ConfigFilename.Value().(string)
18+
19+
RuntimeConfig.gatecheckConfig = gatecheck.NewDefaultConfig()
20+
if configFilename != "" {
21+
err := gatecheck.NewConfigDecoder(configFilename).Decode(RuntimeConfig.gatecheckConfig)
22+
if err != nil {
23+
return err
24+
}
25+
}
5026

51-
slog.Debug("read in config", "filename", configFilename, "target_filename", targetFilename)
27+
var err error
5228

53-
config := gatecheck.NewDefaultConfig()
54-
if configFilename != "" {
55-
err := LoadConfigFromFile(config, configFilename)
29+
epssFilename := RuntimeConfig.EPSSFilename.Value().(string)
30+
if epssFilename != "" {
31+
RuntimeConfig.epssFile, err = os.Open(epssFilename)
32+
}
5633
if err != nil {
5734
return err
5835
}
59-
} else {
60-
slog.Warn("no configuration file given, will use default configuration file")
61-
}
62-
63-
slog.Debug("open target file", "filename", targetFilename)
64-
targetFile, err := os.Open(targetFilename)
65-
if err != nil {
66-
return err
67-
}
6836

69-
var epssFile, kevFile io.Reader
70-
71-
if epssFilename != "" {
72-
slog.Debug("open epss file", "filename", epssFilename)
73-
epssFile, err = os.Open(epssFilename)
37+
kevFilename := RuntimeConfig.KEVFilename.Value().(string)
38+
if kevFilename != "" {
39+
RuntimeConfig.kevFile, err = os.Open(kevFilename)
40+
}
7441
if err != nil {
7542
return err
7643
}
77-
}
7844

79-
if kevFilename != "" {
80-
slog.Debug("open kev file", "filename", kevFilename)
81-
kevFile, err = os.Open(kevFilename)
45+
targetFilename := args[0]
46+
slog.Debug("open target file", "filename", targetFilename)
47+
RuntimeConfig.targetFile, err = os.Open(targetFilename)
8248
if err != nil {
8349
return err
8450
}
85-
}
8651

87-
err = gatecheck.Validate(
88-
config,
89-
targetFile,
90-
targetFilename,
91-
gatecheck.WithEPSSURL(epssURL),
92-
gatecheck.WithKEVURL(kevURL),
93-
gatecheck.WithEPSSFile(epssFile),
94-
gatecheck.WithKEVFile(kevFile),
95-
)
52+
return nil
53+
},
54+
RunE: func(cmd *cobra.Command, args []string) error {
55+
56+
err := gatecheck.Validate(
57+
RuntimeConfig.gatecheckConfig,
58+
RuntimeConfig.targetFile,
59+
args[0],
60+
gatecheck.WithEPSSURL(RuntimeConfig.EPSSURL.Value().(string)),
61+
gatecheck.WithKEVURL(RuntimeConfig.KEVURL.Value().(string)),
62+
gatecheck.WithEPSSFile(RuntimeConfig.epssFile),
63+
gatecheck.WithKEVFile(RuntimeConfig.kevFile),
64+
)
65+
66+
audit := RuntimeConfig.Audit.Value().(bool)
67+
if audit && err != nil {
68+
slog.Error("validation failure in audit mode")
69+
fmt.Fprintln(cmd.ErrOrStderr(), err)
70+
return nil
71+
}
9672

97-
if audit && err != nil {
98-
slog.Error("validation failure in audit mode")
99-
fmt.Fprintln(cmd.ErrOrStderr(), err)
10073
return nil
101-
}
74+
},
75+
}
76+
77+
func newValidateCommand() *cobra.Command {
78+
79+
RuntimeConfig.ConfigFilename.SetupCobra(validateCmd)
80+
RuntimeConfig.EPSSFilename.SetupCobra(validateCmd)
81+
RuntimeConfig.KEVFilename.SetupCobra(validateCmd)
82+
RuntimeConfig.Audit.SetupCobra(validateCmd)
10283

103-
return err
84+
return validateCmd
10485
}

0 commit comments

Comments
 (0)