Skip to content

Commit

Permalink
Merge pull request #14 from armosec/struct
Browse files Browse the repository at this point in the history
Struct
  • Loading branch information
kooomix authored Jan 3, 2024
2 parents fb8ffc6 + 5b9c1ab commit 39360f0
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 61 deletions.
80 changes: 52 additions & 28 deletions armometadata/k8sutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,63 +105,87 @@ func LoadConfig(configPath string) (*ClusterConfig, error) {
return config, err
}

type Metadata struct {
Annotations map[string]string
Labels map[string]string
OwnerReferences map[string]string
CreationTimestamp string
ResourceVersion string
Kind string
ApiVersion string
PodSelectorMatchLabels map[string]string
}

// ExtractMetadataFromBytes extracts metadata from the JSON bytes of a Kubernetes object
func ExtractMetadataFromJsonBytes(input []byte) (error, map[string]string, map[string]string, map[string]string, string, string, string, string) {
func ExtractMetadataFromJsonBytes(input []byte) (Metadata, error) {
// output values
annotations := map[string]string{}
labels := map[string]string{}
ownerReferences := map[string]string{}
creationTs := ""
resourceVersion := ""
kind := ""
apiVersion := ""
m := Metadata{
Annotations: map[string]string{},
Labels: map[string]string{},
OwnerReferences: map[string]string{},
PodSelectorMatchLabels: map[string]string{},
}
// ujson parsing
var parent string
var parent, subParent, subParent2 string
err := ujson.Walk(input, func(level int, key, value []byte) bool {
switch level {
case 1:
if bytes.EqualFold(key, []byte(`"kind"`)) {
kind = unquote(value)
m.Kind = unquote(value)
}

if bytes.EqualFold(key, []byte(`"apiVersion"`)) {
apiVersion = unquote(value)
m.ApiVersion = unquote(value)
}

// skip everything except metadata
if !bytes.EqualFold(key, []byte(`"metadata"`)) {
// skip everything except metadata and spec
if !bytes.EqualFold(key, []byte(`"metadata"`)) && !bytes.EqualFold(key, []byte(`"spec"`)) {
return false
}

parent = unquote(key)
case 2:
// read creationTimestamp
if bytes.EqualFold(key, []byte(`"creationTimestamp"`)) {
creationTs = unquote(value)
}
// read resourceVersion
if bytes.EqualFold(key, []byte(`"resourceVersion"`)) {
resourceVersion = unquote(value)
if parent == "metadata" {
// read creationTimestamp
if bytes.EqualFold(key, []byte(`"creationTimestamp"`)) {
m.CreationTimestamp = unquote(value)
}
// read resourceVersion
if bytes.EqualFold(key, []byte(`"resourceVersion"`)) {
m.ResourceVersion = unquote(value)
}

}

// record parent for level 3
parent = unquote(key)
subParent = unquote(key)

case 3:
// read annotations
if parent == "annotations" {
annotations[unquote(key)] = unquote(value)
if subParent == "annotations" {
m.Annotations[unquote(key)] = unquote(value)
}
// read labels
if parent == "labels" {
labels[unquote(key)] = unquote(value)
if subParent == "labels" {
m.Labels[unquote(key)] = unquote(value)
}

subParent2 = unquote(key)

case 4:
// read ownerReferences
if parent == "ownerReferences" {
ownerReferences[unquote(key)] = unquote(value)
if subParent == "ownerReferences" {
m.OwnerReferences[unquote(key)] = unquote(value)
}

if subParent2 == "matchLabels" {
m.PodSelectorMatchLabels[unquote(key)] = unquote(value)
}

}
return true
})
return err, annotations, labels, ownerReferences, creationTs, resourceVersion, kind, apiVersion
return m, err
}

func unquote(value []byte) string {
Expand Down
95 changes: 62 additions & 33 deletions armometadata/k8sutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,41 @@ func BoolPtr(b bool) *bool {

func TestExtractMetadataFromJsonBytes(t *testing.T) {
tests := []struct {
name string
want error
annotations map[string]string
labels map[string]string
ownerReferences map[string]string
creationTs string
resourceVersion string
kind string
apiVersion string
name string
wantErr error
annotations map[string]string
labels map[string]string
ownerReferences map[string]string
creationTs string
resourceVersion string
kind string
apiVersion string
podSelectorMatchLabels map[string]string
}{
{
name: "networkpolicy_withoutmatching_labels",
annotations: map[string]string{},
labels: map[string]string{},
ownerReferences: map[string]string{},
creationTs: "2023-11-16T10:12:35Z",
resourceVersion: "",
kind: "NetworkPolicy",
apiVersion: "networking.k8s.io/v1",
podSelectorMatchLabels: map[string]string{},
},
{
name: "networkpolicy_withmatching_labels",
annotations: map[string]string{},
labels: map[string]string{},
ownerReferences: map[string]string{},
creationTs: "2023-11-16T10:12:35Z",
resourceVersion: "",
kind: "NetworkPolicy",
apiVersion: "networking.k8s.io/v1",
podSelectorMatchLabels: map[string]string{
"role": "frontend",
},
},
{
name: "applicationactivity",
annotations: map[string]string{
Expand All @@ -147,11 +172,12 @@ func TestExtractMetadataFromJsonBytes(t *testing.T) {
"kubescape.io/workload-name": "storage",
"kubescape.io/workload-namespace": "kubescape",
},
ownerReferences: map[string]string{},
creationTs: "2023-11-16T10:15:05Z",
resourceVersion: "1",
kind: "ApplicationActivity",
apiVersion: "spdx.softwarecomposition.kubescape.io/v1beta1",
ownerReferences: map[string]string{},
creationTs: "2023-11-16T10:15:05Z",
resourceVersion: "1",
kind: "ApplicationActivity",
apiVersion: "spdx.softwarecomposition.kubescape.io/v1beta1",
podSelectorMatchLabels: map[string]string{},
},
{
name: "pod",
Expand All @@ -178,10 +204,11 @@ func TestExtractMetadataFromJsonBytes(t *testing.T) {
"name": "kubescape-549f95c69",
"uid": "c0ff7d3b-4183-482c-81c5-998faf0b6150",
},
creationTs: "2023-11-16T10:12:35Z",
resourceVersion: "59348379",
kind: "Pod",
apiVersion: "v1",
creationTs: "2023-11-16T10:12:35Z",
resourceVersion: "59348379",
kind: "Pod",
apiVersion: "v1",
podSelectorMatchLabels: map[string]string{},
},
{
name: "sbom",
Expand All @@ -193,26 +220,28 @@ func TestExtractMetadataFromJsonBytes(t *testing.T) {
"kubescape.io/image-id": "quay-io-kubescape-kubescape-sha256-608b85d3de51caad84a2bfe089ec",
"kubescape.io/image-name": "quay-io-kubescape-kubescape",
},
ownerReferences: map[string]string{},
creationTs: "2023-11-16T10:13:40Z",
resourceVersion: "1",
kind: "SBOMSPDXv2p3",
apiVersion: "spdx.softwarecomposition.kubescape.io/v1beta1",
ownerReferences: map[string]string{},
creationTs: "2023-11-16T10:13:40Z",
resourceVersion: "1",
kind: "SBOMSPDXv2p3",
apiVersion: "spdx.softwarecomposition.kubescape.io/v1beta1",
podSelectorMatchLabels: map[string]string{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
input, err := os.ReadFile(fmt.Sprintf("testdata/%s.json", tt.name))
assert.NoError(t, err)
got, annotations, labels, ownerReferences, creationTs, resourceVersion, kind, apiVersion := ExtractMetadataFromJsonBytes(input)
assert.Equal(t, tt.want, got)
assert.Equal(t, tt.annotations, annotations)
assert.Equal(t, tt.labels, labels)
assert.Equal(t, tt.ownerReferences, ownerReferences)
assert.Equal(t, tt.creationTs, creationTs)
assert.Equal(t, tt.resourceVersion, resourceVersion)
assert.Equal(t, tt.kind, kind)
assert.Equal(t, tt.apiVersion, apiVersion)
m, err := ExtractMetadataFromJsonBytes(input)
assert.Equal(t, tt.wantErr, err)
assert.Equal(t, tt.annotations, m.Annotations)
assert.Equal(t, tt.labels, m.Labels)
assert.Equal(t, tt.ownerReferences, m.OwnerReferences)
assert.Equal(t, tt.creationTs, m.CreationTimestamp)
assert.Equal(t, tt.resourceVersion, m.ResourceVersion)
assert.Equal(t, tt.kind, m.Kind)
assert.Equal(t, tt.apiVersion, m.ApiVersion)
assert.Equal(t, tt.podSelectorMatchLabels, m.PodSelectorMatchLabels)
})
}
}
Expand All @@ -221,6 +250,6 @@ func BenchmarkExtractMetadataFromJsonBytes(b *testing.B) {
input, err := os.ReadFile("testdata/applicationactivity.json")
assert.NoError(b, err)
for i := 0; i < b.N; i++ {
_, _, _, _, _, _, _, _ = ExtractMetadataFromJsonBytes(input)
_, _ = ExtractMetadataFromJsonBytes(input)
}
}
31 changes: 31 additions & 0 deletions armometadata/testdata/networkpolicy_withmatching_labels.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"apiVersion": "networking.k8s.io/v1",
"kind": "NetworkPolicy",
"metadata": {
"creationTimestamp": "2023-11-16T10:12:35Z",
"name": "allow-frontend-backend",
"namespace": "default"
},
"spec": {
"podSelector": {
"matchLabels": {
"role": "frontend"
}
},
"policyTypes": ["Ingress"],
"ingress": [
{
"from": [
{
"podSelector": {
"matchLabels": {
"role": "backend"
}
}
}
]
}
]
}
}

23 changes: 23 additions & 0 deletions armometadata/testdata/networkpolicy_withoutmatching_labels.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"apiVersion": "networking.k8s.io/v1",
"kind": "NetworkPolicy",
"metadata": {
"creationTimestamp": "2023-11-16T10:12:35Z",
"name": "allow-all-in-namespace",
"namespace": "default"
},
"spec": {
"podSelector": {},
"policyTypes": ["Ingress"],
"ingress": [
{
"from": [
{
"podSelector": {}
}
]
}
]
}
}

0 comments on commit 39360f0

Please sign in to comment.