Skip to content

Commit

Permalink
add method to extract some metadata from raw json
Browse files Browse the repository at this point in the history
Signed-off-by: Matthias Bertschy <[email protected]>
  • Loading branch information
matthyx committed Nov 16, 2023
1 parent 9e6bf6f commit 1f3a3e1
Show file tree
Hide file tree
Showing 7 changed files with 644 additions and 0 deletions.
44 changes: 44 additions & 0 deletions armometadata/k8sutils.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package armometadata

import (
"bytes"
"encoding/json"
"fmt"
"hash/fnv"
"path"
"strings"

"github.com/armosec/utils-k8s-go/wlid"
"github.com/olvrng/ujson"
"github.com/spf13/viper"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -102,3 +104,45 @@ func LoadConfig(configPath string) (*ClusterConfig, error) {
err = json.Unmarshal(res, &config)
return config, err
}

// ExtractMetadataFromBytes extracts metadata from the JSON bytes of a Kubernetes object
func ExtractMetadataFromJsonBytes(input []byte) (error, map[string]string, map[string]string, string) {
// output values
annotations := map[string]string{}
labels := map[string]string{}
creationTs := ""
// ujson parsing
var parent string
err := ujson.Walk(input, func(level int, key, value []byte) bool {
switch level {
case 1:
// skip everything except metadata
if !bytes.EqualFold(key, []byte(`"metadata"`)) {
return false
}
case 2:
// read creationTimestamp
if bytes.EqualFold(key, []byte(`"creationTimestamp"`)) {
creationTs = unquote(value)
}
// record parent for level 3
parent = unquote(key)
case 3:
// read annotations
if parent == "annotations" {
annotations[unquote(key)] = unquote(value)
}
// read labels
if parent == "labels" {
labels[unquote(key)] = unquote(value)
}
}
return true
})
return err, annotations, labels, creationTs
}

func unquote(value []byte) string {
buf, _ := ujson.Unquote(value)
return string(buf)
}
70 changes: 70 additions & 0 deletions armometadata/k8sutils_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package armometadata

import (
"fmt"
"os"
"testing"

"github.com/armosec/armoapi-go/armotypes"
Expand Down Expand Up @@ -119,3 +121,71 @@ func TestLoadClusterConfig(t *testing.T) {
func BoolPtr(b bool) *bool {
return &b
}

func TestExtractMetadataFromJsonBytes(t *testing.T) {
tests := []struct {
name string
want error
annotations map[string]string
labels map[string]string
creationTs string
}{
{
name: "applicationactivity",
annotations: map[string]string{
"kubescape.io/status": "",
"kubescape.io/wlid": "wlid://cluster-gke_armo-test-clusters_us-central1-c_danielg/namespace-kubescape/deployment-storage",
},
labels: map[string]string{
"kubescape.io/workload-api-group": "apps",
"kubescape.io/workload-api-version": "v1",
"kubescape.io/workload-kind": "Deployment",
"kubescape.io/workload-name": "storage",
"kubescape.io/workload-namespace": "kubescape",
},
creationTs: "2023-11-16T10:15:05Z",
},
{
name: "pod",
annotations: map[string]string{
"cni.projectcalico.org/containerID": "d2e279e2ac8fda015bce3d0acf86121f9df8fdf9bf9e028d99d41110ab1b81dc",
"cni.projectcalico.org/podIP": "10.0.2.169/32",
"cni.projectcalico.org/podIPs": "10.0.2.169/32",
},
labels: map[string]string{
"app": "kubescape",
"app.kubernetes.io/instance": "kubescape",
"app.kubernetes.io/name": "kubescape",
"helm.sh/chart": "kubescape-operator-1.16.2",
"helm.sh/revision": "1",
"otel": "enabled",
"pod-template-hash": "549f95c69",
"tier": "ks-control-plane",
},
creationTs: "2023-11-16T10:12:35Z",
},
{
name: "sbom",
annotations: map[string]string{
"kubescape.io/image-id": "quay.io/kubescape/kubescape@sha256:608b85d3de51caad84a2bfe089ec2c5dbc192dbe9dc319849834bf0e678e0523",
"kubescape.io/status": "",
},
labels: map[string]string{
"kubescape.io/image-id": "quay-io-kubescape-kubescape-sha256-608b85d3de51caad84a2bfe089ec",
"kubescape.io/image-name": "quay-io-kubescape-kubescape",
},
creationTs: "2023-11-16T10:13:40Z",
},
}
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, creationTs := ExtractMetadataFromJsonBytes(input)
assert.Equal(t, tt.want, got)
assert.Equal(t, tt.annotations, annotations)
assert.Equal(t, tt.labels, labels)
assert.Equal(t, tt.creationTs, creationTs)
})
}
}
88 changes: 88 additions & 0 deletions armometadata/testdata/applicationactivity.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
{
"apiVersion": "spdx.softwarecomposition.kubescape.io/v1beta1",
"kind": "ApplicationActivity",
"metadata": {
"annotations": {
"kubescape.io/status": "",
"kubescape.io/wlid": "wlid://cluster-gke_armo-test-clusters_us-central1-c_danielg/namespace-kubescape/deployment-storage"
},
"creationTimestamp": "2023-11-16T10:15:05Z",
"labels": {
"kubescape.io/workload-api-group": "apps",
"kubescape.io/workload-api-version": "v1",
"kubescape.io/workload-kind": "Deployment",
"kubescape.io/workload-name": "storage",
"kubescape.io/workload-namespace": "kubescape"
},
"name": "kubescape-replicaset-storage-76d8b6ddfc-aced-6fcf",
"namespace": "kubescape",
"resourceVersion": "1",
"uid": "1e06cb11-4bab-4bed-bca1-8e95982a0d2e"
},
"spec": {
"syscalls": [
"newfstatat",
"setgroups",
"getpeername",
"mmap",
"getdents64",
"rt_sigreturn",
"epoll_pwait",
"execve",
"fcntl",
"getsockopt",
"prctl",
"sched_getaffinity",
"accept4",
"connect",
"pread64",
"sendto",
"uname",
"epoll_create1",
"getppid",
"mkdirat",
"readlinkat",
"madvise",
"recvfrom",
"rt_sigprocmask",
"close",
"gettid",
"setgid",
"statfs",
"getrlimit",
"nanosleep",
"getrandom",
"inotify_init1",
"clone",
"futex",
"fchown",
"fstatfs",
"getpid",
"read",
"tgkill",
"arch_prctl",
"faccessat2",
"ioctl",
"listen",
"openat",
"capset",
"getuid",
"pipe2",
"setuid",
"sigaltstack",
"bind",
"fstat",
"write",
"inotify_add_watch",
"sched_yield",
"getsockname",
"setsockopt",
"socket",
"capget",
"epoll_ctl",
"rt_sigaction",
"chdir"
]
},
"status": {}
}
Loading

0 comments on commit 1f3a3e1

Please sign in to comment.