-
Notifications
You must be signed in to change notification settings - Fork 10
/
k8s.go
128 lines (111 loc) · 3.01 KB
/
k8s.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
// © 2022-2023 Snyk Limited All rights reserved.
//
// 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 legacyiac
import (
"sort"
"strings"
"github.com/snyk/policy-engine/pkg/models"
)
type K8sInput struct {
resourceNamespace string
resourceType string
resourceId string
document map[string]interface{}
}
func NewK8sInputs(state *models.State) []Input {
inputs := []Input{}
// Need to be deterministic for tests.
resourceTypes := []string{}
for resourceType := range state.Resources {
resourceTypes = append(resourceTypes, resourceType)
}
sort.Strings(resourceTypes)
for _, resourceType := range resourceTypes {
resources := state.Resources[resourceType]
// Need to be deterministic for tests.
resourceKeys := []string{}
for key := range resources {
resourceKeys = append(resourceKeys, key)
}
sort.Strings(resourceKeys)
for _, k := range resourceKeys {
r := resources[k]
input := K8sInput{
resourceNamespace: r.Namespace,
resourceType: r.ResourceType,
resourceId: r.Id,
document: r.Attributes,
}
inputs = append(inputs, &input)
}
}
return inputs
}
func (k *K8sInput) Raw() interface{} {
return k.document
}
func (k *K8sInput) ParseMsg(msg string) ParsedMsg {
path := parsePath(msg)
// Some paths may start with "kind.", remove that part.
if len(path) > 0 {
if resourceType, ok := path[0].(string); ok &&
strings.ToLower(resourceType) == strings.ToLower(k.resourceType) {
path = path[1:]
}
}
rewritePath(path, k.document)
return ParsedMsg{
ResourceID: k.resourceId,
ResourceType: k.resourceType,
ResourceNamespace: k.resourceNamespace,
Path: path,
}
}
func rewritePath(path []interface{}, document interface{}) {
cursor := document
for pathIdx := range path {
switch parent := cursor.(type) {
case map[string]interface{}:
switch k := path[pathIdx].(type) {
case string:
if child, ok := parent[k]; ok {
cursor = child
continue
}
}
case []interface{}:
switch i := path[pathIdx].(type) {
case int:
if i >= 0 && i < len(parent) {
cursor = parent[i]
continue
}
case string:
for actual, elem := range parent {
if obj, ok := elem.(map[string]interface{}); ok {
if name, ok := obj["name"]; ok {
if namestr := name.(string); ok && namestr == i {
path[pathIdx] = actual
cursor = elem
continue
}
}
}
}
}
}
// Stop on type mismatches and non-nested types.
return
}
}