From 2d5a7604e70a3fbb26e4e43cb0e985bb69a5c853 Mon Sep 17 00:00:00 2001 From: Joel Takvorian Date: Tue, 5 Nov 2024 14:54:06 +0100 Subject: [PATCH 1/2] NETOBSERV-1890: decode TCP flags (new stage/rule) --- docs/api.md | 4 +++ pkg/api/transform_network.go | 2 ++ pkg/pipeline/transform/transform_network.go | 11 +++++++- pkg/utils/tcp_flags.go | 30 +++++++++++++++++++++ pkg/utils/tcp_flags_test.go | 18 +++++++++++++ 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 pkg/utils/tcp_flags.go create mode 100644 pkg/utils/tcp_flags_test.go diff --git a/docs/api.md b/docs/api.md index ccecab368..9db6a67ac 100644 --- a/docs/api.md +++ b/docs/api.md @@ -241,6 +241,7 @@ Following is the supported API format for network transformations: add_kubernetes_infra: add output kubernetes isInfra field from input reinterpret_direction: reinterpret flow direction at the node level (instead of net interface), to ease the deduplication process add_subnet_label: categorize IPs based on known subnets configuration + decode_tcp_flags: decode bitwise TCP flags into a string kubernetes_infra: Kubernetes infra rule configuration namespaceNameFields: entries for namespace and name input fields name: name of the object @@ -272,6 +273,9 @@ Following is the supported API format for network transformations: input: entry input field output: entry output field protocol: entry protocol field + decode_tcp_flags: Decode bitwise TCP flags into a string + input: entry input field + output: entry output field kubeConfig: global configuration related to Kubernetes (optional) configPath: path to kubeconfig file (optional) secondaryNetworks: configuration for secondary networks diff --git a/pkg/api/transform_network.go b/pkg/api/transform_network.go index baf922230..a83e385d9 100644 --- a/pkg/api/transform_network.go +++ b/pkg/api/transform_network.go @@ -59,6 +59,7 @@ const ( NetworkAddKubernetesInfra TransformNetworkOperationEnum = "add_kubernetes_infra" // add output kubernetes isInfra field from input NetworkReinterpretDirection TransformNetworkOperationEnum = "reinterpret_direction" // reinterpret flow direction at the node level (instead of net interface), to ease the deduplication process NetworkAddSubnetLabel TransformNetworkOperationEnum = "add_subnet_label" // categorize IPs based on known subnets configuration + NetworkDecodeTCPFlags TransformNetworkOperationEnum = "decode_tcp_flags" // decode bitwise TCP flags into a string ) type NetworkTransformRule struct { @@ -69,6 +70,7 @@ type NetworkTransformRule struct { AddLocation *NetworkGenericRule `yaml:"add_location,omitempty" json:"add_location,omitempty" doc:"Add location rule configuration"` AddSubnetLabel *NetworkAddSubnetLabelRule `yaml:"add_subnet_label,omitempty" json:"add_subnet_label,omitempty" doc:"Add subnet label rule configuration"` AddService *NetworkAddServiceRule `yaml:"add_service,omitempty" json:"add_service,omitempty" doc:"Add service rule configuration"` + DecodeTCPFlags *NetworkGenericRule `yaml:"decode_tcp_flags,omitempty" json:"decode_tcp_flags,omitempty" doc:"Decode bitwise TCP flags into a string"` } type K8sInfraRule struct { diff --git a/pkg/pipeline/transform/transform_network.go b/pkg/pipeline/transform/transform_network.go index b79e6759c..15d391b72 100644 --- a/pkg/pipeline/transform/transform_network.go +++ b/pkg/pipeline/transform/transform_network.go @@ -22,6 +22,7 @@ import ( "net" "os" "strconv" + "strings" "time" "github.com/netobserv/flowlogs-pipeline/pkg/api" @@ -141,6 +142,13 @@ func (n *Network) Transform(inputEntry config.GenericMap) (config.GenericMap, bo } } } + case api.NetworkDecodeTCPFlags: + if anyFlags, ok := outputEntry[rule.DecodeTCPFlags.Input]; ok && anyFlags != nil { + if flags, ok := anyFlags.(uint16); ok { + flags := util.DecodeTCPFlags(flags) + outputEntry[rule.DecodeTCPFlags.Output] = strings.Join(flags, ",") + } + } default: log.Panicf("unknown type %s for transform.Network rule: %v", rule.Type, rule) @@ -194,7 +202,8 @@ func NewTransformNetwork(params config.StageParam, opMetrics *operational.Metric if len(jsonNetworkTransform.SubnetLabels) == 0 { return nil, fmt.Errorf("a rule '%s' was found, but there are no subnet labels configured", api.NetworkAddSubnetLabel) } - case api.NetworkAddSubnet: + case api.NetworkAddSubnet, api.NetworkDecodeTCPFlags: + // nothing } } diff --git a/pkg/utils/tcp_flags.go b/pkg/utils/tcp_flags.go new file mode 100644 index 000000000..c07d3f37b --- /dev/null +++ b/pkg/utils/tcp_flags.go @@ -0,0 +1,30 @@ +package utils + +type tcpFlag struct { + value uint16 + name string +} + +var tcpFlags = []tcpFlag{ + {value: 1, name: "FIN"}, + {value: 2, name: "SYN"}, + {value: 4, name: "RST"}, + {value: 8, name: "PSH"}, + {value: 16, name: "ACK"}, + {value: 32, name: "URG"}, + {value: 64, name: "ECE"}, + {value: 128, name: "CWR"}, + {value: 256, name: "SYN_ACK"}, + {value: 512, name: "FIN_ACK"}, + {value: 1024, name: "RST_ACK"}, +} + +func DecodeTCPFlags(bitfield uint16) []string { + var values []string + for _, flag := range tcpFlags { + if bitfield&flag.value != 0 { + values = append(values, flag.name) + } + } + return values +} diff --git a/pkg/utils/tcp_flags_test.go b/pkg/utils/tcp_flags_test.go new file mode 100644 index 000000000..2765d1d24 --- /dev/null +++ b/pkg/utils/tcp_flags_test.go @@ -0,0 +1,18 @@ +package utils + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDecodeFlags(t *testing.T) { + flags528 := DecodeTCPFlags(528) + assert.Equal(t, []string{"ACK", "FIN_ACK"}, flags528) + + flags256 := DecodeTCPFlags(256) + assert.Equal(t, []string{"SYN_ACK"}, flags256) + + flags666 := DecodeTCPFlags(666) + assert.Equal(t, []string{"SYN", "PSH", "ACK", "CWR", "FIN_ACK"}, flags666) +} From 974b3f54d5505fa13c91323816ffadafc53c86aa Mon Sep 17 00:00:00 2001 From: Joel Takvorian Date: Thu, 14 Nov 2024 11:05:34 +0100 Subject: [PATCH 2/2] Use flags list --- pkg/pipeline/transform/transform_network.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/pipeline/transform/transform_network.go b/pkg/pipeline/transform/transform_network.go index 15d391b72..09934ae7e 100644 --- a/pkg/pipeline/transform/transform_network.go +++ b/pkg/pipeline/transform/transform_network.go @@ -22,7 +22,6 @@ import ( "net" "os" "strconv" - "strings" "time" "github.com/netobserv/flowlogs-pipeline/pkg/api" @@ -146,7 +145,7 @@ func (n *Network) Transform(inputEntry config.GenericMap) (config.GenericMap, bo if anyFlags, ok := outputEntry[rule.DecodeTCPFlags.Input]; ok && anyFlags != nil { if flags, ok := anyFlags.(uint16); ok { flags := util.DecodeTCPFlags(flags) - outputEntry[rule.DecodeTCPFlags.Output] = strings.Join(flags, ",") + outputEntry[rule.DecodeTCPFlags.Output] = flags } }