Skip to content

Commit

Permalink
cmd/observe: Add traffic direction filter
Browse files Browse the repository at this point in the history
Before this patch, it was not possible to filter flows by traffic
direction.

Signed-off-by: Alexandre Perrin <alex@isovalent.com>
  • Loading branch information
kaworu committed Apr 4, 2023
1 parent a1aa0e9 commit 64dac69
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 59 deletions.
3 changes: 3 additions & 0 deletions cmd/observe/flows.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,9 @@ func newFlowsCmdHelper(usage cmdUsage, vp *viper.Viper, ofilter *flowFilter) *co
filterFlags.Var(filterVar(
"to-identity", ofilter,
"Show all flows terminating at an endpoint with the given security identity"))
filterFlags.Var(filterVar(
"traffic-direction", ofilter,
"Show all flows in the given traffic direction (either ingress or egress)"))

rawFilterFlags := pflag.NewFlagSet("raw-filters", pflag.ContinueOnError)
rawFilterFlags.StringArray(allowlistFlag, []string{}, "Specify allowlist as JSON encoded FlowFilters")
Expand Down
16 changes: 16 additions & 0 deletions cmd/observe/flows_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ func newFlowFilter() *flowFilter {
{"node-name"},
{"tcp-flags"},
{"uuid"},
{"traffic-direction"},
},
}
}
Expand Down Expand Up @@ -555,6 +556,21 @@ func (of *flowFilter) set(f *filterTracker, name, val string, track bool) error
f.apply(func(f *flowpb.FlowFilter) {
f.TcpFlags = append(f.TcpFlags, flags)
})

// traffic direction filter
case "traffic-direction":
switch td := strings.ToLower(val); td {
case "ingress":
f.apply(func(f *flowpb.FlowFilter) {
f.TrafficDirection = append(f.TrafficDirection, flowpb.TrafficDirection_INGRESS)
})
case "egress":
f.apply(func(f *flowpb.FlowFilter) {
f.TrafficDirection = append(f.TrafficDirection, flowpb.TrafficDirection_EGRESS)
})
default:
return fmt.Errorf("%s: invalid traffic direction, expected ingress or egress", td)
}
}

return nil
Expand Down
59 changes: 59 additions & 0 deletions cmd/observe/flows_filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,3 +433,62 @@ func TestUuid(t *testing.T) {
}
assert.Nil(t, f.blacklist)
}

func TestTrafficDirection(t *testing.T) {
tt := []struct {
name string
flags []string
filters []*flowpb.FlowFilter
err string
}{
{
name: "ingress",
flags: []string{"--traffic-direction", "ingress"},
filters: []*flowpb.FlowFilter{
{TrafficDirection: []flowpb.TrafficDirection{flowpb.TrafficDirection_INGRESS}},
},
},
{
name: "egress",
flags: []string{"--traffic-direction", "egress"},
filters: []*flowpb.FlowFilter{
{TrafficDirection: []flowpb.TrafficDirection{flowpb.TrafficDirection_EGRESS}},
},
},
{
name: "mixed case",
flags: []string{"--traffic-direction", "INGRESS", "--traffic-direction", "EgrEss"},
filters: []*flowpb.FlowFilter{
{
TrafficDirection: []flowpb.TrafficDirection{
flowpb.TrafficDirection_INGRESS,
flowpb.TrafficDirection_EGRESS,
},
},
},
},
{
name: "invalid",
flags: []string{"--traffic-direction", "to the moon"},
err: "to the moon: invalid traffic direction, expected ingress or egress",
},
}

for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
f := newFlowFilter()
cmd := newFlowsCmdWithFilter(viper.New(), f)
err := cmd.Flags().Parse(tc.flags)
diff := cmp.Diff(tc.filters, f.whitelist.flowFilters(), cmpopts.IgnoreUnexported(flowpb.FlowFilter{}))
if diff != "" {
t.Errorf("mismatch (-want +got):\n%s", diff)
}
if tc.err != "" {
assert.Errorf(t, err, tc.err)
} else {
assert.NoError(t, err)
}
assert.Nil(t, f.blacklist)
})
}
}
119 changes: 60 additions & 59 deletions cmd/observe_help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,65 +38,66 @@ Selectors Flags:


Filters Flags:
--fqdn filter Show all flows related to the given fully qualified domain name (e.g. "*.cilium.io").
--from-fqdn filter Show all flows originating at the given fully qualified domain name (e.g. "*.cilium.io").
--from-identity filter Show all flows originating at an endpoint with the given security identity
--from-ip filter Show all flows originating at the given IP address. Each of the source IPs can be specified as an exact match (e.g. '1.1.1.1') or as a CIDR range (e.g.'1.1.1.0/24').
--from-label filter Show only flows originating in an endpoint with the given labels (e.g. "key1=value1", "reserved:world")
--from-namespace filter Show all flows originating in the given Kubernetes namespace.
--from-pod filter Show all flows originating in the given pod name prefix([namespace/]<pod-name>). If namespace is not provided, 'default' is used
--from-port filter Show only flows with the given source port (e.g. 8080)
--from-service filter Shows flows where the source IP address matches the ClusterIP address of the given service name prefix([namespace/]<svc-name>). If namespace is not provided, 'default' is used
--from-workload filter Show all flows originating at an endpoint with the given workload
--http-method filter Show only flows which match this HTTP method (e.g. "get", "post")
--http-path filter Show only flows which match this HTTP path regular expressions (e.g. "/page/\\d+")
--http-status filter Show only flows which match this HTTP status code prefix (e.g. "404", "5+")
--identity filter Show all flows related to an endpoint with the given security identity
--ip filter Show all flows related to the given IP address. Each of the IPs can be specified as an exact match (e.g. '1.1.1.1') or as a CIDR range (e.g.'1.1.1.0/24').
--ip-version filter Show only IPv4, IPv6 flows or non IP flows (e.g. ARP packets) (ie: "none", "v4", "v6")
-4, --ipv4 filter[=v4] Show only IPv4 flows
-6, --ipv6 filter[=v6] Show only IPv6 flows
-l, --label filter Show only flows related to an endpoint with the given labels (e.g. "key1=value1", "reserved:world")
-n, --namespace filter Show all flows related to the given Kubernetes namespace.
--node-name filter Show all flows which match the given node names (e.g. "k8s*", "test-cluster/*.company.com")
--not filter[=true] Reverses the next filter to be blacklist i.e. --not --from-ip 2.2.2.2
--pod filter Show all flows related to the given pod name prefix ([namespace/]<pod-name>). If namespace is not provided, 'default' is used.
--port filter Show only flows with given port in either source or destination (e.g. 8080)
--protocol filter Show only flows which match the given L4/L7 flow protocol (e.g. "udp", "http")
--service filter Shows flows where either the source or destination IP address matches the ClusterIP address of the given service name prefix ([namespace/]<svc-name>). If namespace is not provided, 'default' is used.
--tcp-flags filter Show only flows which match the given TCP flags (e.g. "syn", "ack", "fin")
--to-fqdn filter Show all flows terminating at the given fully qualified domain name (e.g. "*.cilium.io").
--to-identity filter Show all flows terminating at an endpoint with the given security identity
--to-ip filter Show all flows terminating at the given IP address. Each of the destination IPs can be specified as an exact match (e.g. '1.1.1.1') or as a CIDR range (e.g.'1.1.1.0/24').
--to-label filter Show only flows terminating in an endpoint with given labels (e.g. "key1=value1", "reserved:world")
--to-namespace filter Show all flows terminating in the given Kubernetes namespace.
--to-pod filter Show all flows terminating in the given pod name prefix([namespace/]<pod-name>). If namespace is not provided, 'default' is used
--to-port filter Show only flows with the given destination port (e.g. 8080)
--to-service filter Shows flows where the destination IP address matches the ClusterIP address of the given service name prefix ([namespace/]<svc-name>). If namespace is not provided, 'default' is used
--to-workload filter Show all flows terminating at an endpoint with the given workload
--trace-id filter Show only flows which match this trace ID
-t, --type filter Filter by event types TYPE[:SUBTYPE]. Available types and subtypes:
TYPE SUBTYPE
capture n/a
drop n/a
l7 n/a
policy-verdict n/a
trace from-endpoint
from-host
from-network
from-overlay
from-proxy
from-stack
to-endpoint
to-host
to-network
to-overlay
to-proxy
to-stack
trace-sock n/a
--uuid filter Show the only flow matching this unique flow identifier, if any
--verdict filter Show only flows with this verdict [FORWARDED, DROPPED, AUDIT, REDIRECTED, ERROR, TRACED, TRANSLATED]
--workload filter Show all flows related to an endpoint with the given workload
--fqdn filter Show all flows related to the given fully qualified domain name (e.g. "*.cilium.io").
--from-fqdn filter Show all flows originating at the given fully qualified domain name (e.g. "*.cilium.io").
--from-identity filter Show all flows originating at an endpoint with the given security identity
--from-ip filter Show all flows originating at the given IP address. Each of the source IPs can be specified as an exact match (e.g. '1.1.1.1') or as a CIDR range (e.g.'1.1.1.0/24').
--from-label filter Show only flows originating in an endpoint with the given labels (e.g. "key1=value1", "reserved:world")
--from-namespace filter Show all flows originating in the given Kubernetes namespace.
--from-pod filter Show all flows originating in the given pod name prefix([namespace/]<pod-name>). If namespace is not provided, 'default' is used
--from-port filter Show only flows with the given source port (e.g. 8080)
--from-service filter Shows flows where the source IP address matches the ClusterIP address of the given service name prefix([namespace/]<svc-name>). If namespace is not provided, 'default' is used
--from-workload filter Show all flows originating at an endpoint with the given workload
--http-method filter Show only flows which match this HTTP method (e.g. "get", "post")
--http-path filter Show only flows which match this HTTP path regular expressions (e.g. "/page/\\d+")
--http-status filter Show only flows which match this HTTP status code prefix (e.g. "404", "5+")
--identity filter Show all flows related to an endpoint with the given security identity
--ip filter Show all flows related to the given IP address. Each of the IPs can be specified as an exact match (e.g. '1.1.1.1') or as a CIDR range (e.g.'1.1.1.0/24').
--ip-version filter Show only IPv4, IPv6 flows or non IP flows (e.g. ARP packets) (ie: "none", "v4", "v6")
-4, --ipv4 filter[=v4] Show only IPv4 flows
-6, --ipv6 filter[=v6] Show only IPv6 flows
-l, --label filter Show only flows related to an endpoint with the given labels (e.g. "key1=value1", "reserved:world")
-n, --namespace filter Show all flows related to the given Kubernetes namespace.
--node-name filter Show all flows which match the given node names (e.g. "k8s*", "test-cluster/*.company.com")
--not filter[=true] Reverses the next filter to be blacklist i.e. --not --from-ip 2.2.2.2
--pod filter Show all flows related to the given pod name prefix ([namespace/]<pod-name>). If namespace is not provided, 'default' is used.
--port filter Show only flows with given port in either source or destination (e.g. 8080)
--protocol filter Show only flows which match the given L4/L7 flow protocol (e.g. "udp", "http")
--service filter Shows flows where either the source or destination IP address matches the ClusterIP address of the given service name prefix ([namespace/]<svc-name>). If namespace is not provided, 'default' is used.
--tcp-flags filter Show only flows which match the given TCP flags (e.g. "syn", "ack", "fin")
--to-fqdn filter Show all flows terminating at the given fully qualified domain name (e.g. "*.cilium.io").
--to-identity filter Show all flows terminating at an endpoint with the given security identity
--to-ip filter Show all flows terminating at the given IP address. Each of the destination IPs can be specified as an exact match (e.g. '1.1.1.1') or as a CIDR range (e.g.'1.1.1.0/24').
--to-label filter Show only flows terminating in an endpoint with given labels (e.g. "key1=value1", "reserved:world")
--to-namespace filter Show all flows terminating in the given Kubernetes namespace.
--to-pod filter Show all flows terminating in the given pod name prefix([namespace/]<pod-name>). If namespace is not provided, 'default' is used
--to-port filter Show only flows with the given destination port (e.g. 8080)
--to-service filter Shows flows where the destination IP address matches the ClusterIP address of the given service name prefix ([namespace/]<svc-name>). If namespace is not provided, 'default' is used
--to-workload filter Show all flows terminating at an endpoint with the given workload
--trace-id filter Show only flows which match this trace ID
--traffic-direction filter Show all flows in the given traffic direction (either ingress or egress)
-t, --type filter Filter by event types TYPE[:SUBTYPE]. Available types and subtypes:
TYPE SUBTYPE
capture n/a
drop n/a
l7 n/a
policy-verdict n/a
trace from-endpoint
from-host
from-network
from-overlay
from-proxy
from-stack
to-endpoint
to-host
to-network
to-overlay
to-proxy
to-stack
trace-sock n/a
--uuid filter Show the only flow matching this unique flow identifier, if any
--verdict filter Show only flows with this verdict [FORWARDED, DROPPED, AUDIT, REDIRECTED, ERROR, TRACED, TRANSLATED]
--workload filter Show all flows related to an endpoint with the given workload

Raw-Filters Flags:
--allowlist stringArray Specify allowlist as JSON encoded FlowFilters
Expand Down

0 comments on commit 64dac69

Please sign in to comment.