-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
compliance.go
93 lines (81 loc) · 2.76 KB
/
compliance.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
package spec
import (
"fmt"
"os"
"strings"
"github.com/samber/lo"
"golang.org/x/xerrors"
"gopkg.in/yaml.v3"
sp "github.com/aquasecurity/trivy-checks/pkg/spec"
iacTypes "github.com/aquasecurity/trivy/pkg/iac/types"
"github.com/aquasecurity/trivy/pkg/types"
)
type Severity string
// ComplianceSpec represent the compliance specification
type ComplianceSpec struct {
Spec iacTypes.Spec `yaml:"spec"`
}
const (
FailStatus iacTypes.ControlStatus = "FAIL"
PassStatus iacTypes.ControlStatus = "PASS"
WarnStatus iacTypes.ControlStatus = "WARN"
)
// Scanners reads spec control and determines the scanners by check ID prefix
func (cs *ComplianceSpec) Scanners() (types.Scanners, error) {
scannerTypes := make(map[types.Scanner]struct{})
for _, control := range cs.Spec.Controls {
for _, check := range control.Checks {
scannerType := scannerByCheckID(check.ID)
if scannerType == types.UnknownScanner {
return nil, xerrors.Errorf("unsupported check ID: %s", check.ID)
}
scannerTypes[scannerType] = struct{}{}
}
}
return lo.Keys(scannerTypes), nil
}
// CheckIDs return list of compliance check IDs
func (cs *ComplianceSpec) CheckIDs() map[types.Scanner][]string {
checkIDsMap := make(map[types.Scanner][]string)
for _, control := range cs.Spec.Controls {
for _, check := range control.Checks {
scannerType := scannerByCheckID(check.ID)
checkIDsMap[scannerType] = append(checkIDsMap[scannerType], check.ID)
}
}
return checkIDsMap
}
func scannerByCheckID(checkID string) types.Scanner {
checkID = strings.ToLower(checkID)
switch {
case strings.HasPrefix(checkID, "cve-") || strings.HasPrefix(checkID, "dla-"):
return types.VulnerabilityScanner
case strings.HasPrefix(checkID, "avd-"):
return types.MisconfigScanner
case strings.HasPrefix(checkID, "vuln-"): // custom id for filtering vulnerabilities by severity
return types.VulnerabilityScanner
case strings.HasPrefix(checkID, "secret-"): // custom id for filtering secrets by severity
return types.SecretScanner
default:
return types.UnknownScanner
}
}
// GetComplianceSpec accepct compliance flag name/path and return builtin or file system loaded spec
func GetComplianceSpec(specNameOrPath string) (ComplianceSpec, error) {
var b []byte
var err error
if strings.HasPrefix(specNameOrPath, "@") {
b, err = os.ReadFile(strings.TrimPrefix(specNameOrPath, "@"))
if err != nil {
return ComplianceSpec{}, fmt.Errorf("error retrieving compliance spec from path: %w", err)
}
} else {
// TODO: GetSpecByName() should return []byte
b = []byte(sp.NewSpecLoader().GetSpecByName(specNameOrPath))
}
var complianceSpec ComplianceSpec
if err = yaml.Unmarshal(b, &complianceSpec); err != nil {
return ComplianceSpec{}, xerrors.Errorf("spec yaml decode error: %w", err)
}
return complianceSpec, nil
}