-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Field selectors support in RuleMatchObjectExtend and scan object supp…
…ort in httpserver API (#127) * added fields selected to RuleMatchObjects Signed-off-by: Amir Malka <[email protected]> * omitempty fieldselector Signed-off-by: Amir Malka <[email protected]> * scan workload support in httpserver api Signed-off-by: Amir Malka <[email protected]> * CR changes Signed-off-by: Amir Malka <[email protected]> * increase coverage Signed-off-by: Amir Malka <[email protected]> --------- Signed-off-by: Amir Malka <[email protected]>
- Loading branch information
Showing
4 changed files
with
302 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
package objectsenvelopes | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
|
||
"github.com/kubescape/k8s-interface/k8sinterface" | ||
"github.com/kubescape/k8s-interface/workloadinterface" | ||
) | ||
|
||
var _ workloadinterface.IMetadata = (*ScanObject)(nil) | ||
|
||
type ScanObjectMetadata struct { | ||
Name string `json:"name"` | ||
Namespace string `json:"namespace,omitempty"` | ||
} | ||
|
||
// A ScanObject represents a K8S object to be scanned | ||
type ScanObject struct { | ||
ApiVersion string `json:"apiVersion"` | ||
Kind string `json:"kind"` | ||
Metadata ScanObjectMetadata `json:"metadata"` | ||
} | ||
|
||
func IsTypeScanObject(object map[string]interface{}) bool { | ||
if object == nil { | ||
return false | ||
} | ||
|
||
if _, ok := object["apiVersion"]; !ok { | ||
return false | ||
} | ||
if _, ok := object["kind"]; !ok { | ||
return false | ||
} | ||
|
||
if _, ok := object["metadata"]; !ok { | ||
return false | ||
} | ||
|
||
metadata, ok := object["metadata"].(map[string]interface{}) | ||
if !ok { | ||
return false | ||
} | ||
|
||
if _, ok = metadata["name"]; !ok { | ||
return false | ||
} | ||
|
||
return true | ||
} | ||
|
||
// NewScanObject construct a ScanObject from map[string]interface{}. If the map does not match the object, will return nil | ||
func NewScanObject(object map[string]interface{}) *ScanObject { | ||
if !IsTypeScanObject(object) { | ||
return nil | ||
} | ||
|
||
scanObject := &ScanObject{} | ||
if b := workloadinterface.MapToBytes(object); b != nil { | ||
if err := json.Unmarshal(b, scanObject); err != nil { | ||
return nil | ||
} | ||
} else { | ||
return nil | ||
} | ||
return scanObject | ||
} | ||
|
||
func (scanObject *ScanObject) GetNamespace() string { | ||
return scanObject.Metadata.GetNamespace() | ||
} | ||
|
||
func (scanObjectMetadata *ScanObjectMetadata) GetName() string { | ||
return scanObjectMetadata.Name | ||
} | ||
|
||
func (scanObjectMetadata *ScanObjectMetadata) GetNamespace() string { | ||
return scanObjectMetadata.Namespace | ||
} | ||
|
||
func (scanObjectMetadata *ScanObjectMetadata) SetName(name string) { | ||
scanObjectMetadata.Name = name | ||
} | ||
|
||
func (scanObjectMetadata *ScanObjectMetadata) SetNamespace(namespace string) { | ||
scanObjectMetadata.Namespace = namespace | ||
} | ||
|
||
func (scanObject *ScanObject) GetName() string { | ||
return scanObject.Metadata.GetName() | ||
} | ||
|
||
func (scanObject *ScanObject) GetKind() string { | ||
return scanObject.Kind | ||
} | ||
|
||
func (scanObject *ScanObject) GetApiVersion() string { | ||
return scanObject.ApiVersion | ||
} | ||
|
||
func (scanObject *ScanObject) GetWorkload() map[string]interface{} { | ||
return scanObject.GetObject() | ||
} | ||
|
||
func (scanObject *ScanObject) GetObject() map[string]interface{} { | ||
m := map[string]interface{}{} | ||
b, err := json.Marshal(*scanObject) | ||
if err != nil { | ||
return m | ||
} | ||
return workloadinterface.BytesToMap(b) | ||
} | ||
|
||
func (scanObject *ScanObject) GetID() string { | ||
return fmt.Sprintf("%s/%s/%s/%s", k8sinterface.JoinGroupVersion(k8sinterface.SplitApiVersion(scanObject.GetApiVersion())), scanObject.GetNamespace(), scanObject.GetKind(), scanObject.GetName()) | ||
} | ||
|
||
func (scanObject *ScanObject) GetObjectType() workloadinterface.ObjectType { | ||
return GetObjectType(scanObject.GetObject()) | ||
} | ||
|
||
func (scanObject *ScanObject) SetNamespace(namespace string) { | ||
scanObject.Metadata.SetNamespace(namespace) | ||
} | ||
|
||
func (scanObject *ScanObject) SetName(name string) { | ||
scanObject.Metadata.SetName(name) | ||
} | ||
|
||
func (scanObject *ScanObject) SetKind(kind string) { | ||
scanObject.Kind = kind | ||
} | ||
|
||
func (scanObject *ScanObject) SetWorkload(object map[string]interface{}) { | ||
scanObject.SetObject(object) | ||
} | ||
|
||
func (scanObject *ScanObject) SetObject(object map[string]interface{}) { | ||
if !IsTypeScanObject(object) { | ||
return | ||
} | ||
if b := workloadinterface.MapToBytes(object); len(b) > 0 { | ||
obj := &ScanObject{} | ||
if err := json.Unmarshal(b, obj); err == nil { | ||
scanObject.SetApiVersion(obj.GetApiVersion()) | ||
scanObject.SetKind(obj.GetKind()) | ||
scanObject.SetName(obj.GetName()) | ||
scanObject.SetNamespace(obj.GetNamespace()) | ||
} | ||
} | ||
} | ||
|
||
func (scanObject *ScanObject) SetApiVersion(apiVersion string) { | ||
scanObject.ApiVersion = apiVersion | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package objectsenvelopes | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
|
||
"github.com/kubescape/k8s-interface/workloadinterface" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestNewScanObject(t *testing.T) { | ||
// Test nil input | ||
assert.Nil(t, NewScanObject(nil)) | ||
|
||
// Test valid input | ||
object := map[string]interface{}{ | ||
"kind": "Pod", | ||
"apiVersion": "v1", | ||
"metadata": map[string]interface{}{ | ||
"name": "test-pod", | ||
"namespace": "test-namespace", | ||
}, | ||
} | ||
scanObj := NewScanObject(object) | ||
assert.NotNil(t, scanObj) | ||
assert.Equal(t, "Pod", scanObj.GetKind()) | ||
assert.Equal(t, "v1", scanObj.GetApiVersion()) | ||
assert.Equal(t, "test-pod", scanObj.GetName()) | ||
assert.Equal(t, "test-namespace", scanObj.GetNamespace()) | ||
assert.Equal(t, workloadinterface.TypeWorkloadObject, scanObj.GetObjectType()) | ||
|
||
// Test unsupported input | ||
unsupportedObject := map[string]interface{}{ | ||
"unknown": "unknown", | ||
} | ||
assert.Nil(t, NewScanObject(unsupportedObject)) | ||
} | ||
|
||
func TestScanObjectMarshal(t *testing.T) { | ||
scanObj := ScanObject{ | ||
Kind: "Pod", | ||
ApiVersion: "v1", | ||
Metadata: ScanObjectMetadata{ | ||
Name: "test-pod", | ||
Namespace: "test-namespace", | ||
}, | ||
} | ||
|
||
// test json marshal | ||
jsonEnc, err := json.Marshal(scanObj) | ||
expectedJsonStr := `{"apiVersion":"v1","kind":"Pod","metadata":{"name":"test-pod","namespace":"test-namespace"}}` | ||
assert.NoError(t, err) | ||
assert.Equal(t, expectedJsonStr, string(jsonEnc)) | ||
} | ||
|
||
func TestScanObjectUnmarshal(t *testing.T) { | ||
var scanObj ScanObject | ||
jsonStr := `{"apiVersion":"v1","kind":"Node","metadata":{"name":"node-1"},"field":"value"}` | ||
err := json.Unmarshal([]byte(jsonStr), &scanObj) | ||
assert.NoError(t, err) | ||
assert.Equal(t, "Node", scanObj.GetKind()) | ||
assert.Equal(t, "node-1", scanObj.GetName()) | ||
assert.Equal(t, "", scanObj.GetNamespace()) | ||
} | ||
|
||
func TestScanObjectSetters(t *testing.T) { | ||
scanObj := ScanObject{} | ||
|
||
scanObj.SetKind("Node") | ||
assert.Equal(t, "Node", scanObj.Kind) | ||
|
||
scanObj.SetApiVersion("v2") | ||
assert.Equal(t, "v2", scanObj.ApiVersion) | ||
|
||
scanObj.SetName("node-1") | ||
assert.Equal(t, "node-1", scanObj.Metadata.Name) | ||
|
||
scanObj.SetNamespace("namespace") | ||
assert.Equal(t, "namespace", scanObj.Metadata.Namespace) | ||
|
||
// test invalid objects - should remain unchanged | ||
scanObj.SetObject(map[string]interface{}{ | ||
"invalid": "object", | ||
}) | ||
scanObj.SetObject(map[string]interface{}{ | ||
"apiVersion": "v3", | ||
}) | ||
scanObj.SetObject(map[string]interface{}{ | ||
"apiVersion": "v3", | ||
"kind": "Secret", | ||
}) | ||
scanObj.SetObject(map[string]interface{}{ | ||
"apiVersion": "v3", | ||
"kind": "Secret", | ||
"metadata": "invalid_type", | ||
}) | ||
scanObj.SetObject(map[string]interface{}{ | ||
"apiVersion": "v3", | ||
"kind": "Secret", | ||
"metadata": map[string]interface{}{ | ||
"namespace": "ns-1", | ||
}, | ||
}) | ||
assert.Equal(t, "Node", scanObj.Kind) | ||
|
||
scanObj.SetObject(map[string]interface{}{ | ||
"kind": "Pod", | ||
"apiVersion": "v1", | ||
"metadata": map[string]interface{}{ | ||
"name": "test-pod", | ||
}, | ||
}) | ||
assert.Equal(t, "Pod", scanObj.Kind) | ||
assert.Equal(t, "v1", scanObj.ApiVersion) | ||
assert.Equal(t, "test-pod", scanObj.Metadata.Name) | ||
} | ||
|
||
func TestScanObjectGetters(t *testing.T) { | ||
scanObj := ScanObject{ | ||
Kind: "Pod", | ||
ApiVersion: "v1", | ||
Metadata: ScanObjectMetadata{ | ||
Name: "test-pod", | ||
Namespace: "test-namespace", | ||
}, | ||
} | ||
|
||
assert.Equal(t, "Pod", scanObj.GetKind()) | ||
assert.Equal(t, "v1", scanObj.GetApiVersion()) | ||
assert.Equal(t, "test-pod", scanObj.GetName()) | ||
assert.Equal(t, "test-namespace", scanObj.GetNamespace()) | ||
assert.Equal(t, workloadinterface.TypeWorkloadObject, scanObj.GetObjectType()) | ||
assert.Equal(t, "/v1/test-namespace/Pod/test-pod", scanObj.GetID()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters