From 3e01900d339988ce9704d1d60cf27a3bcda85677 Mon Sep 17 00:00:00 2001 From: Nico Feulner Date: Thu, 11 Jan 2024 10:54:02 +0000 Subject: [PATCH] feat: add group ID option This adds the option to set the group ID via command line and via annotation Signed-off-by: Nico Feulner --- .../deployment/linkerd-cni.conf.default | 1 + .../manifests/calico/linkerd-cni.yaml | 1 + .../manifests/cilium/linkerd-cni.yaml | 1 + .../manifests/flannel/linkerd-cni.yaml | 1 + cni-plugin/integration/testutil/test_util.go | 7 +++++++ cni-plugin/main.go | 21 +++++++++++++++++++ internal/iptables/iptables.go | 17 +++++++++++++++ proxy-init/cmd/root.go | 4 ++++ proxy-init/cmd/root_test.go | 3 +++ .../iptables/iptablestest-lab.yaml | 12 +++++------ 10 files changed, 62 insertions(+), 6 deletions(-) diff --git a/cni-plugin/deployment/linkerd-cni.conf.default b/cni-plugin/deployment/linkerd-cni.conf.default index a7e699fe..68f76cef 100644 --- a/cni-plugin/deployment/linkerd-cni.conf.default +++ b/cni-plugin/deployment/linkerd-cni.conf.default @@ -14,6 +14,7 @@ "incoming-proxy-port": 4143, "outgoing-proxy-port": 4140, "proxy-uid": 2102, + "proxy-gid": 2102, "ports-to-redirect": [], "inbound-ports-to-ignore": [], "outbound-ports-to-ignore": [], diff --git a/cni-plugin/integration/manifests/calico/linkerd-cni.yaml b/cni-plugin/integration/manifests/calico/linkerd-cni.yaml index 05f110bd..b12fc08b 100644 --- a/cni-plugin/integration/manifests/calico/linkerd-cni.yaml +++ b/cni-plugin/integration/manifests/calico/linkerd-cni.yaml @@ -77,6 +77,7 @@ data: "incoming-proxy-port": 4143, "outgoing-proxy-port": 4140, "proxy-uid": 2102, + "proxy-gid": 2102, "ports-to-redirect": [], "inbound-ports-to-ignore": ["4191","4190"], "simulate": false, diff --git a/cni-plugin/integration/manifests/cilium/linkerd-cni.yaml b/cni-plugin/integration/manifests/cilium/linkerd-cni.yaml index 05f110bd..b12fc08b 100644 --- a/cni-plugin/integration/manifests/cilium/linkerd-cni.yaml +++ b/cni-plugin/integration/manifests/cilium/linkerd-cni.yaml @@ -77,6 +77,7 @@ data: "incoming-proxy-port": 4143, "outgoing-proxy-port": 4140, "proxy-uid": 2102, + "proxy-gid": 2102, "ports-to-redirect": [], "inbound-ports-to-ignore": ["4191","4190"], "simulate": false, diff --git a/cni-plugin/integration/manifests/flannel/linkerd-cni.yaml b/cni-plugin/integration/manifests/flannel/linkerd-cni.yaml index 5b9166ad..7db733ad 100644 --- a/cni-plugin/integration/manifests/flannel/linkerd-cni.yaml +++ b/cni-plugin/integration/manifests/flannel/linkerd-cni.yaml @@ -81,6 +81,7 @@ data: "incoming-proxy-port": 4143, "outgoing-proxy-port": 4140, "proxy-uid": 2102, + "proxy-gid": 2102, "ports-to-redirect": [], "inbound-ports-to-ignore": ["4191","4190"], "simulate": false, diff --git a/cni-plugin/integration/testutil/test_util.go b/cni-plugin/integration/testutil/test_util.go index 3d2429e9..f97a7d70 100644 --- a/cni-plugin/integration/testutil/test_util.go +++ b/cni-plugin/integration/testutil/test_util.go @@ -46,6 +46,7 @@ type ProxyInit struct { IncomingProxyPort int `json:"incoming-proxy-port"` OutgoingProxyPort int `json:"outgoing-proxy-port"` ProxyUID int `json:"proxy-uid"` + ProxyGID int `json:"proxy-gid"` PortsToRedirect []int `json:"ports-to-redirect"` InboundPortsToIgnore []string `json:"inbound-ports-to-ignore"` OutboundPortsToIgnore []string `json:"outbound-ports-to-ignore"` @@ -70,6 +71,7 @@ type LinkerdPlugin struct { // "incoming-proxy-port": 4143, // "outgoing-proxy-port": 4140, // "proxy-uid": 2102, +// "proxy-gid": 2102, // "ports-to-redirect": [], // "inbound-ports-to-ignore": ["4191","4190"], // "simulate": false, @@ -110,6 +112,11 @@ func checkLinkerdCniConf(plugin map[string]any) error { return fmt.Errorf("proxy-uid has wrong value, expected: %v, found: %v", 2102, proxyUID) } + proxyGID := proxyInit.ProxyGID + if proxyGID != 2102 { + return fmt.Errorf("proxy-gid has wrong value, expected: %v, found: %v", 2102, proxyUID) + } + simulate := proxyInit.Simulate if simulate { return fmt.Errorf("simulate has wrong value, expected: %v, found: %v", false, simulate) diff --git a/cni-plugin/main.go b/cni-plugin/main.go index 9a01be75..e6967dc0 100644 --- a/cni-plugin/main.go +++ b/cni-plugin/main.go @@ -46,6 +46,7 @@ type ProxyInit struct { IncomingProxyPort int `json:"incoming-proxy-port"` OutgoingProxyPort int `json:"outgoing-proxy-port"` ProxyUID int `json:"proxy-uid"` + ProxyGID int `json:"proxy-gid"` PortsToRedirect []int `json:"ports-to-redirect"` InboundPortsToIgnore []string `json:"inbound-ports-to-ignore"` OutboundPortsToIgnore []string `json:"outbound-ports-to-ignore"` @@ -212,6 +213,7 @@ func cmdAdd(args *skel.CmdArgs) error { IncomingProxyPort: conf.ProxyInit.IncomingProxyPort, OutgoingProxyPort: conf.ProxyInit.OutgoingProxyPort, ProxyUserID: conf.ProxyInit.ProxyUID, + ProxyGroupID: conf.ProxyInit.ProxyGID, PortsToRedirect: conf.ProxyInit.PortsToRedirect, InboundPortsToIgnore: conf.ProxyInit.InboundPortsToIgnore, OutboundPortsToIgnore: conf.ProxyInit.OutboundPortsToIgnore, @@ -277,6 +279,25 @@ func cmdAdd(args *skel.CmdArgs) error { options.ProxyUserID = parsed } + // Override ProxyGID from annotations. + proxyGIDOverride, err := getAnnotationOverride(ctx, client, pod, "config.linkerd.io/proxy-gid") + if err != nil { + logEntry.Errorf("linkerd-cni: could not retrieve overridden annotations: %s", err) + return err + } + + if proxyGIDOverride != "" { + logEntry.Debugf("linkerd-cni: overriding ProxyGID to %s", proxyGIDOverride) + + parsed, err := strconv.Atoi(proxyGIDOverride) + if err != nil { + logEntry.Errorf("linkerd-cni: could not parse ProxyGID to integer: %s", err) + return err + } + + options.ProxyGroupID = parsed + } + if pod.GetLabels()["linkerd.io/control-plane-component"] != "" { // Skip k8s api server ports on the outbound side if pod is a // control plane component diff --git a/internal/iptables/iptables.go b/internal/iptables/iptables.go index 4356c04b..b6d50ce6 100644 --- a/internal/iptables/iptables.go +++ b/internal/iptables/iptables.go @@ -53,6 +53,7 @@ type FirewallConfiguration struct { ProxyInboundPort int ProxyOutgoingPort int ProxyUID int + ProxyGID int SimulateOnly bool NetNs string UseWaitFlag bool @@ -117,6 +118,11 @@ func (fc FirewallConfiguration) addOutgoingTrafficRules(existingRules []byte, co commands = append(commands, fc.makeIgnoreUserID(outputChainName, fc.ProxyUID, "ignore-proxy-user-id")) } + // Ignore traffic from the proxy + if fc.ProxyGID > 0 { + commands = append(commands, fc.makeIgnoreGroupID(outputChainName, fc.ProxyGID, "ignore-proxy-group-id")) + } + // Ignore loopback commands = append(commands, fc.makeIgnoreLoopback(outputChainName, "ignore-loopback")) // Ignore ports @@ -264,6 +270,17 @@ func (fc FirewallConfiguration) makeIgnoreUserID(chainName string, uid int, comm "--comment", formatComment(comment)) } +func (fc FirewallConfiguration) makeIgnoreGroupID(chainName string, gid int, comment string) *exec.Cmd { + return exec.Command(fc.BinPath, + "-t", "nat", + "-A", chainName, + "-m", "owner", + "--gid-owner", strconv.Itoa(gid), + "-j", "RETURN", + "-m", "comment", + "--comment", formatComment(comment)) +} + func (fc FirewallConfiguration) makeFlushChain(name string) *exec.Cmd { return exec.Command(fc.BinPath, "-t", "nat", diff --git a/proxy-init/cmd/root.go b/proxy-init/cmd/root.go index 6b8d1504..d1b322dd 100644 --- a/proxy-init/cmd/root.go +++ b/proxy-init/cmd/root.go @@ -18,6 +18,7 @@ type RootOptions struct { IncomingProxyPort int OutgoingProxyPort int ProxyUserID int + ProxyGroupID int PortsToRedirect []int InboundPortsToIgnore []string OutboundPortsToIgnore []string @@ -37,6 +38,7 @@ func newRootOptions() *RootOptions { IncomingProxyPort: -1, OutgoingProxyPort: -1, ProxyUserID: -1, + ProxyGroupID: -1, PortsToRedirect: make([]int, 0), InboundPortsToIgnore: make([]string, 0), OutboundPortsToIgnore: make([]string, 0), @@ -91,6 +93,7 @@ func NewRootCmd() *cobra.Command { cmd.PersistentFlags().IntVarP(&options.IncomingProxyPort, "incoming-proxy-port", "p", options.IncomingProxyPort, "Port to redirect incoming traffic") cmd.PersistentFlags().IntVarP(&options.OutgoingProxyPort, "outgoing-proxy-port", "o", options.OutgoingProxyPort, "Port to redirect outgoing traffic") cmd.PersistentFlags().IntVarP(&options.ProxyUserID, "proxy-uid", "u", options.ProxyUserID, "User ID that the proxy is running under. Any traffic coming from this user will be ignored to avoid infinite redirection loops.") + cmd.PersistentFlags().IntVarP(&options.ProxyGroupID, "proxy-gid", "g", options.ProxyGroupID, "Group ID that the proxy is running under. Any traffic coming from this group will be ignored to avoid infinite redirection loops.") cmd.PersistentFlags().IntSliceVarP(&options.PortsToRedirect, "ports-to-redirect", "r", options.PortsToRedirect, "Port to redirect to proxy, if no port is specified then ALL ports are redirected") cmd.PersistentFlags().StringSliceVar(&options.InboundPortsToIgnore, "inbound-ports-to-ignore", options.InboundPortsToIgnore, "Inbound ports and/or port ranges (inclusive) to ignore and not redirect to proxy. This has higher precedence than any other parameters.") cmd.PersistentFlags().StringSliceVar(&options.OutboundPortsToIgnore, "outbound-ports-to-ignore", options.OutboundPortsToIgnore, "Outbound ports and/or port ranges (inclusive) to ignore and not redirect to proxy. This has higher precedence than any other parameters.") @@ -131,6 +134,7 @@ func BuildFirewallConfiguration(options *RootOptions) (*iptables.FirewallConfigu ProxyInboundPort: options.IncomingProxyPort, ProxyOutgoingPort: options.OutgoingProxyPort, ProxyUID: options.ProxyUserID, + ProxyGID: options.ProxyGroupID, PortsToRedirectInbound: options.PortsToRedirect, InboundPortsToIgnore: options.InboundPortsToIgnore, OutboundPortsToIgnore: options.OutboundPortsToIgnore, diff --git a/proxy-init/cmd/root_test.go b/proxy-init/cmd/root_test.go index 06908d7d..1ba3373c 100644 --- a/proxy-init/cmd/root_test.go +++ b/proxy-init/cmd/root_test.go @@ -12,6 +12,7 @@ func TestBuildFirewallConfiguration(t *testing.T) { expectedIncomingProxyPort := 1234 expectedOutgoingProxyPort := 2345 expectedProxyUserID := 33 + expectedProxyGroupID := 33 expectedConfig := &iptables.FirewallConfiguration{ Mode: iptables.RedirectAllMode, PortsToRedirectInbound: make([]int, 0), @@ -21,6 +22,7 @@ func TestBuildFirewallConfiguration(t *testing.T) { ProxyInboundPort: expectedIncomingProxyPort, ProxyOutgoingPort: expectedOutgoingProxyPort, ProxyUID: expectedProxyUserID, + ProxyGID: expectedProxyGroupID, SimulateOnly: false, UseWaitFlag: false, BinPath: "iptables", @@ -31,6 +33,7 @@ func TestBuildFirewallConfiguration(t *testing.T) { options.IncomingProxyPort = expectedIncomingProxyPort options.OutgoingProxyPort = expectedOutgoingProxyPort options.ProxyUserID = expectedProxyUserID + options.ProxyGroupID = expectedProxyGroupID config, err := BuildFirewallConfiguration(options) if err != nil { diff --git a/proxy-init/integration/iptables/iptablestest-lab.yaml b/proxy-init/integration/iptables/iptablestest-lab.yaml index a9094caf..768b70e0 100644 --- a/proxy-init/integration/iptables/iptablestest-lab.yaml +++ b/proxy-init/integration/iptables/iptablestest-lab.yaml @@ -73,7 +73,7 @@ spec: - name: iptables-test image: test.l5d.io/linkerd/proxy-init:test imagePullPolicy: Never - args: ["-p", "8080", "-o", "8080", "-u", "2102"] + args: ["-p", "8080", "-o", "8080", "-u", "2102", "-g", "2102"] securityContext: allowPrivilegeEscalation: false capabilities: @@ -90,7 +90,7 @@ spec: - name: linkerd-init image: test.l5d.io/linkerd/proxy-init:test imagePullPolicy: Never - args: ["-p", "8080", "-o", "8080", "-u", "2102"] + args: ["-p", "8080", "-o", "8080", "-u", "2102", "-g", "2102"] securityContext: allowPrivilegeEscalation: false capabilities: @@ -144,7 +144,7 @@ spec: - name: linkerd-init image: test.l5d.io/linkerd/proxy-init:test imagePullPolicy: Never - args: ["-p", "8080", "-o", "8080", "-u", "2102"] + args: ["-p", "8080", "-o", "8080", "-u", "2102", "-g", "2102"] securityContext: allowPrivilegeEscalation: false capabilities: @@ -201,7 +201,7 @@ spec: - name: linkerd-init image: test.l5d.io/linkerd/proxy-init:test imagePullPolicy: Never - args: ["-p", "8080", "-o", "8080", "-u", "2102", "-r", "9090", "-r", "9099"] + args: ["-p", "8080", "-o", "8080", "-u", "2102", "-g", "2102", "-r", "9090", "-r", "9099"] securityContext: allowPrivilegeEscalation: false capabilities: @@ -264,7 +264,7 @@ spec: - name: linkerd-init image: test.l5d.io/linkerd/proxy-init:test imagePullPolicy: Never - args: ["-p", "8080", "-o", "8080", "-u", "2102", "--inbound-ports-to-ignore", "6000-8000"] + args: ["-p", "8080", "-o", "8080", "-u", "2102", "-g", "2102", "--inbound-ports-to-ignore", "6000-8000"] securityContext: allowPrivilegeEscalation: false capabilities: @@ -318,7 +318,7 @@ spec: - name: linkerd-init image: test.l5d.io/linkerd/proxy-init:test imagePullPolicy: Never - args: ["-p", "8080", "-o", "8080", "-u", "2102", "--subnets-to-ignore", "0.0.0.0/0"] + args: ["-p", "8080", "-o", "8080", "-u", "2102", "-g", "2102", "--subnets-to-ignore", "0.0.0.0/0"] securityContext: allowPrivilegeEscalation: false capabilities: