-
Notifications
You must be signed in to change notification settings - Fork 23
/
bench.go
130 lines (112 loc) · 3.8 KB
/
bench.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright © 2019 Aqua Security Software Ltd. <info@aquasec.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package check
import (
"fmt"
"strings"
"github.com/golang/glog"
"gopkg.in/yaml.v3"
)
// Bench implementer of this interface represent audit types to be tests.
type Bench interface {
RegisterAuditType(auditType AuditType, typeCallback func() interface{}) error
NewControls(in []byte, definitions []string, customConfigs ...interface{}) (*Controls, error)
}
type bench struct {
auditTypeRegistry map[AuditType]func() interface{}
}
// NewBench returns a new Bench
func NewBench() Bench {
return &bench{auditTypeRegistry: make(map[AuditType]func() interface{})}
}
func (b *bench) RegisterAuditType(auditType AuditType, typeCallback func() interface{}) error {
if _, ok := b.auditTypeRegistry[auditType]; ok {
return fmt.Errorf("audit type %v already registered", auditType)
}
a := typeCallback()
if _, ok := a.(Auditer); ok {
b.auditTypeRegistry[auditType] = typeCallback
return nil
}
return fmt.Errorf("audit type %v must implement Auditer interface", auditType)
}
func (b *bench) NewControls(in []byte, definitions []string, customConfigs ...interface{}) (*Controls, error) {
c := new(Controls)
err := yaml.Unmarshal(in, c)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal YAML: %s", err)
}
c.customConfigs = customConfigs
if len(definitions) > 0 {
c.DefinedConstraints = map[string][]string{}
for _, val := range definitions {
a := strings.Split(val, "=")
// If its type 'category=value' for example 'platform=ubuntu'
if len(a) == 2 && a[0] != "" && a[1] != "" {
c.DefinedConstraints[a[0]] = append(c.DefinedConstraints[a[0]], a[1])
} else {
glog.V(1).Info("failed to parse defined constraint, ", val)
}
}
}
if err := b.extractAllAudits(c); err != nil {
return nil, err
}
return c, nil
}
func (b *bench) convertAuditToRegisteredType(auditType AuditType, audit interface{}) (auditer Auditer, err error) {
var auditBytes []byte
var callback func() interface{}
var ok bool
if auditType == "" || auditType == TypeAudit {
if s, ok := audit.(string); ok || audit == nil {
return Audit(s), nil
}
return nil, fmt.Errorf("failed to convert audit, mismatching type")
}
if callback, ok = b.auditTypeRegistry[auditType]; !ok {
return nil, fmt.Errorf("audit type %v is not registered", auditType)
}
o := callback()
if auditBytes, err = yaml.Marshal(audit); err != nil {
return nil, fmt.Errorf("unable to marshal Audit %v", err)
}
if err := yaml.Unmarshal(auditBytes, o); err != nil {
return nil, fmt.Errorf("unable to Unmarshal Audit %v", err)
}
return o.(Auditer), nil
}
func (b *bench) extractAllAudits(controls *Controls) (err error) {
var audit Auditer
for _, group := range controls.Groups {
for _, check := range group.Checks {
if check.SubChecks == nil {
if audit, err = b.convertAuditToRegisteredType(check.AuditType, check.Audit); err != nil {
return err
}
check.auditer = audit
check.customConfigs = controls.customConfigs
} else {
for _, subCheck := range check.SubChecks {
if audit, err = b.convertAuditToRegisteredType(subCheck.AuditType, subCheck.Audit); err != nil {
return err
}
subCheck.auditer = audit
subCheck.customConfigs = controls.customConfigs
}
}
}
}
return err
}