Skip to content
This repository has been archived by the owner on Jul 11, 2023. It is now read-only.

injector: support inbound port exclusions #3594

Merged
merged 1 commit into from
Jun 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions charts/osm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ The following table lists the configurable parameters of the osm chart and their
| OpenServiceMesh.image.registry | string | `"openservicemesh"` | Container image registry |
| OpenServiceMesh.image.tag | string | `"v0.9.0"` | Container image tag |
| OpenServiceMesh.imagePullSecrets | list | `[]` | `osm-controller` image pull secret |
| OpenServiceMesh.inboundPortExclusionList | list | `[]` | Specifies a global list of ports to exclude from inbound traffic interception by the sidecar proxy. If specified, must be a list of positive integers. |
| OpenServiceMesh.injector.autoScale | object | `{"enable":false,"maxReplicas":5,"minReplicas":1,"targetAverageUtilization":80}` | Auto scale configuration |
| OpenServiceMesh.injector.autoScale.enable | bool | `false` | Enable Autoscale |
| OpenServiceMesh.injector.autoScale.maxReplicas | int | `5` | Maximum replicas for autoscale |
Expand Down
7 changes: 7 additions & 0 deletions charts/osm/crds/meshconfig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ spec:
type: integer
minimum: 1
maximum: 65535
inboundPortExclusionList:
description: Global list of ports to exclude from inbound traffic interception by the sidecar proxy.
type: array
items:
type: integer
minimum: 1
maximum: 65535
useHTTPSIngress:
description: Enable HTTPS ingress on the mesh
type: boolean
Expand Down
1 change: 1 addition & 0 deletions charts/osm/templates/preset-mesh-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ spec:
useHTTPSIngress: {{.Values.OpenServiceMesh.useHTTPSIngress}}
enablePermissiveTrafficPolicyMode: {{.Values.OpenServiceMesh.enablePermissiveTrafficPolicy}}
outboundPortExclusionList: {{.Values.OpenServiceMesh.outboundPortExclusionList}}
inboundPortExclusionList: {{.Values.OpenServiceMesh.inboundPortExclusionList}}
outboundIPRangeExclusionList: {{.Values.OpenServiceMesh.outboundIPRangeExclusionList}}
observability:
enableDebugServer: {{.Values.OpenServiceMesh.enableDebugServer}}
Expand Down
17 changes: 17 additions & 0 deletions charts/osm/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,23 @@
]
]
},
"inboundPortExclusionList": {
"$id": "#/properties/OpenServiceMesh/properties/inboundPortExclusionList",
"type": "array",
"title": "The inboundPortExclusionList schema",
"description": "Inbound port exluclusion list for sidecar traffic interception",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 65535
},
"examples": [
[
6379,
3315
]
]
},
"grafana": {
"$id": "#/properties/OpenServiceMesh/properties/grafana",
"type": "object",
Expand Down
4 changes: 4 additions & 0 deletions charts/osm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ OpenServiceMesh:
# If specified, must be a list of positive integers.
outboundPortExclusionList: []

# -- Specifies a global list of ports to exclude from inbound traffic interception by the sidecar proxy.
# If specified, must be a list of positive integers.
inboundPortExclusionList: []

#
# -- OSM's sidecar injector parameters
injector:
Expand Down
1 change: 1 addition & 0 deletions docs/example/manifests/meshconfig/mesh-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ spec:
observability:
enableDebugServer: true
outboundPortExclusionList: []
inboundPortExclusionList: []
outboundIPRangeExclusionList: []
tracing:
enable: false
Expand Down
3 changes: 3 additions & 0 deletions pkg/apis/config/v1alpha1/mesh_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ type TrafficSpec struct {
// OutboundPortExclusionList defines a global list of ports to exclude from outbound traffic interception by the sidecar proxy.
OutboundPortExclusionList []int `json:"outboundPortExclusionList,omitempty"`

// InboundPortExclusionList defines a global list of ports to exclude from inbound traffic interception by the sidecar proxy.
InboundPortExclusionList []int `json:"inboundPortExclusionList,omitempty"`

// UseHTTPSIngress defines a boolean indicating if HTTPS Ingress is enabled globally in the mesh.
UseHTTPSIngress bool `json:"useHTTPSIngress,omitempty"`

Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/config/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions pkg/configurator/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ func (c *Client) GetOutboundPortExclusionList() []int {
return c.getMeshConfig().Spec.Traffic.OutboundPortExclusionList
}

// GetInboundPortExclusionList returns the list of ports (positive integers) to exclude from inbound sidecar interception
func (c *Client) GetInboundPortExclusionList() []int {
return c.getMeshConfig().Spec.Traffic.InboundPortExclusionList
}

// IsPrivilegedInitContainer returns whether init containers should be privileged
func (c *Client) IsPrivilegedInitContainer() bool {
return c.getMeshConfig().Spec.Sidecar.EnablePrivilegedInitContainer
Expand Down
15 changes: 15 additions & 0 deletions pkg/configurator/methods_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,21 @@ func TestCreateUpdateConfig(t *testing.T) {
assert.Equal([]int{7070, 6080}, cfg.GetOutboundPortExclusionList())
},
},
{
name: "GetIboundPortExclusionList",
initialMeshConfigData: &v1alpha1.MeshConfigSpec{},
checkCreate: func(assert *tassert.Assertions, cfg Configurator) {
assert.Nil(cfg.GetInboundPortExclusionList())
},
updatedMeshConfigData: &v1alpha1.MeshConfigSpec{
Traffic: v1alpha1.TrafficSpec{
InboundPortExclusionList: []int{7070, 6080},
},
},
checkUpdate: func(assert *tassert.Assertions, cfg Configurator) {
assert.Equal([]int{7070, 6080}, cfg.GetInboundPortExclusionList())
},
},
{
name: "IsPrivilegedInitContainer",
initialMeshConfigData: &v1alpha1.MeshConfigSpec{
Expand Down
14 changes: 14 additions & 0 deletions pkg/configurator/mock_client_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions pkg/configurator/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ type Configurator interface {
// GetOutboundPortExclusionList returns the list of ports to exclude from outbound sidecar interception
GetOutboundPortExclusionList() []int

// GetInboundPortExclusionList returns the list of ports to exclude from inbound sidecar interception
GetInboundPortExclusionList() []int

// IsPrivilegedInitContainer determines whether init containers should be privileged
IsPrivilegedInitContainer() bool

Expand Down
4 changes: 2 additions & 2 deletions pkg/injector/init_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
)

func getInitContainerSpec(containerName string, cfg configurator.Configurator, outboundIPRangeExclusionList []string, outboundPortExclusionList []int,
enablePrivilegedInitContainer bool) corev1.Container {
iptablesInitCommandsList := generateIptablesCommands(outboundIPRangeExclusionList, outboundPortExclusionList)
inboundPortExclusionList []int, enablePrivilegedInitContainer bool) corev1.Container {
iptablesInitCommandsList := generateIptablesCommands(outboundIPRangeExclusionList, outboundPortExclusionList, inboundPortExclusionList)
iptablesInitCommand := strings.Join(iptablesInitCommandsList, " && ")

return corev1.Container{
Expand Down
20 changes: 6 additions & 14 deletions pkg/injector/init_container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,10 @@ var _ = Describe("Test functions creating Envoy bootstrap configuration", func()
mockConfigurator := configurator.NewMockConfigurator(mockCtrl)

Context("test getInitContainerSpec()", func() {
It("Creates init container without outbound ip range exclusion list", func() {
It("Creates init container without ip range exclusion list", func() {
mockConfigurator.EXPECT().GetInitContainerImage().Return(containerImage).Times(1)
var outboundIPRangeExclusionList []string = nil
var outboundPortExclusionList []int = nil
privileged := privilegedFalse
actual := getInitContainerSpec(containerName, mockConfigurator, outboundIPRangeExclusionList, outboundPortExclusionList, privileged)
actual := getInitContainerSpec(containerName, mockConfigurator, nil, nil, nil, privileged)

expected := corev1.Container{
Name: "-container-name-",
Expand Down Expand Up @@ -59,9 +57,8 @@ var _ = Describe("Test functions creating Envoy bootstrap configuration", func()
It("Creates init container with outbound exclusion list", func() {
mockConfigurator.EXPECT().GetInitContainerImage().Return(containerImage).Times(1)
outboundIPRangeExclusionList := []string{"1.1.1.1/32", "10.0.0.10/24"}
var outboundPortExclusionList []int = nil
privileged := privilegedFalse
actual := getInitContainerSpec(containerName, mockConfigurator, outboundIPRangeExclusionList, outboundPortExclusionList, privileged)
actual := getInitContainerSpec(containerName, mockConfigurator, outboundIPRangeExclusionList, nil, nil, privileged)

expected := corev1.Container{
Name: "-container-name-",
Expand Down Expand Up @@ -91,10 +88,8 @@ var _ = Describe("Test functions creating Envoy bootstrap configuration", func()

It("Creates init container with privileged true", func() {
mockConfigurator.EXPECT().GetInitContainerImage().Return(containerImage).Times(1)
var outboundIPRangeExclusionList []string = nil
var outboundPortExclusionList []int = nil
privileged := privilegedTrue
actual := getInitContainerSpec(containerName, mockConfigurator, outboundIPRangeExclusionList, outboundPortExclusionList, privileged)
actual := getInitContainerSpec(containerName, mockConfigurator, nil, nil, nil, privileged)

expected := corev1.Container{
Name: "-container-name-",
Expand Down Expand Up @@ -124,10 +119,8 @@ var _ = Describe("Test functions creating Envoy bootstrap configuration", func()

It("Creates init container without outbound port exclusion list", func() {
mockConfigurator.EXPECT().GetInitContainerImage().Return(containerImage).Times(1)
var outboundIPRangeExclusionList []string = nil
var outboundPortExclusionList []int = nil
privileged := privilegedFalse
actual := getInitContainerSpec(containerName, mockConfigurator, outboundIPRangeExclusionList, outboundPortExclusionList, privileged)
actual := getInitContainerSpec(containerName, mockConfigurator, nil, nil, nil, privileged)

expected := corev1.Container{
Name: "-container-name-",
Expand Down Expand Up @@ -157,10 +150,9 @@ var _ = Describe("Test functions creating Envoy bootstrap configuration", func()

It("init container with outbound port exclusion list", func() {
mockConfigurator.EXPECT().GetInitContainerImage().Return(containerImage).Times(1)
var outboundIPRangeExclusionList []string = nil
outboundPortExclusionList := []int{6060, 7070}
privileged := privilegedFalse
actual := getInitContainerSpec(containerName, mockConfigurator, outboundIPRangeExclusionList, outboundPortExclusionList, privileged)
actual := getInitContainerSpec(containerName, mockConfigurator, nil, outboundPortExclusionList, nil, privileged)

expected := corev1.Container{
Name: "-container-name-",
Expand Down
15 changes: 13 additions & 2 deletions pkg/injector/iptables.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ var iptablesInboundStaticRules = []string{
}

// generateIptablesCommands generates a list of iptables commands to set up sidecar interception and redirection
func generateIptablesCommands(outboundIPRangeExclusionList []string, outboundPortExclusionList []int) []string {
func generateIptablesCommands(outboundIPRangeExclusionList []string, outboundPortExclusionList []int, inboundPortExclusionList []int) []string {
var cmd []string

// 1. Create redirection chains
Expand All @@ -89,7 +89,7 @@ func generateIptablesCommands(outboundIPRangeExclusionList []string, outboundPor
cmd = append(cmd, rule)
}

// 5. Create dynamic outbound ports exclusion rule
// 5. Create dynamic outbound ports exclusion rules
if len(outboundPortExclusionList) > 0 {
var portExclusionListStr []string
for _, port := range outboundPortExclusionList {
Expand All @@ -100,5 +100,16 @@ func generateIptablesCommands(outboundIPRangeExclusionList []string, outboundPor
cmd = append(cmd, rule)
}

// 6. Create dynamic inbound ports exclusion rules
if len(inboundPortExclusionList) > 0 {
var portExclusionListStr []string
for _, port := range inboundPortExclusionList {
portExclusionListStr = append(portExclusionListStr, strconv.Itoa(port))
}
inboundPortsToExclude := strings.Join(portExclusionListStr, ",")
rule := fmt.Sprintf("iptables -t nat -I PROXY_INBOUND -p tcp --match multiport --dports %s -j RETURN", inboundPortsToExclude)
cmd = append(cmd, rule)
}

return cmd
}
43 changes: 43 additions & 0 deletions pkg/injector/iptables_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package injector

import (
"testing"

tassert "github.com/stretchr/testify/assert"
)

func TestGenerateIptablesCommands(t *testing.T) {
assert := tassert.New(t)

outboundIPRangeExclusion := []string{"1.1.1.1/32", "2.2.2.2/32"}
outboundPortExclusion := []int{10, 20}
inboundPortExclusion := []int{30, 40}

actual := generateIptablesCommands(outboundIPRangeExclusion, outboundPortExclusion, inboundPortExclusion)

expected := []string{
"iptables -t nat -N PROXY_INBOUND",
"iptables -t nat -N PROXY_IN_REDIRECT",
"iptables -t nat -N PROXY_OUTPUT",
"iptables -t nat -N PROXY_REDIRECT",
"iptables -t nat -A PROXY_REDIRECT -p tcp -j REDIRECT --to-port 15001",
"iptables -t nat -A PROXY_REDIRECT -p tcp --dport 15000 -j ACCEPT",
"iptables -t nat -A OUTPUT -p tcp -j PROXY_OUTPUT",
"iptables -t nat -A PROXY_OUTPUT -m owner --uid-owner 1500 -j RETURN",
"iptables -t nat -A PROXY_OUTPUT -d 127.0.0.1/32 -j RETURN",
"iptables -t nat -A PROXY_OUTPUT -j PROXY_REDIRECT",
"iptables -t nat -A PROXY_IN_REDIRECT -p tcp -j REDIRECT --to-port 15003",
"iptables -t nat -A PREROUTING -p tcp -j PROXY_INBOUND",
"iptables -t nat -A PROXY_INBOUND -p tcp --dport 15010 -j RETURN",
"iptables -t nat -A PROXY_INBOUND -p tcp --dport 15901 -j RETURN",
"iptables -t nat -A PROXY_INBOUND -p tcp --dport 15902 -j RETURN",
"iptables -t nat -A PROXY_INBOUND -p tcp --dport 15903 -j RETURN",
"iptables -t nat -A PROXY_INBOUND -p tcp -j PROXY_IN_REDIRECT",
"iptables -t nat -I PROXY_OUTPUT -d 1.1.1.1/32 -j RETURN",
"iptables -t nat -I PROXY_OUTPUT -d 2.2.2.2/32 -j RETURN",
"iptables -t nat -I PROXY_OUTPUT -p tcp --match multiport --dports 10,20 -j RETURN",
"iptables -t nat -I PROXY_INBOUND -p tcp --match multiport --dports 30,40 -j RETURN",
}

assert.ElementsMatch(expected, actual)
}
25 changes: 14 additions & 11 deletions pkg/injector/patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,18 @@ func (wh *mutatingWebhook) createPatch(pod *corev1.Pod, req *admissionv1.Admissi
// Create volume for envoy TLS secret
pod.Spec.Volumes = append(pod.Spec.Volumes, getVolumeSpec(envoyBootstrapConfigName)...)

podOutboundPortExclusionList, _ := wh.getPodOutboundPortExclusionList(pod, namespace)
// Build outbound port exclusion list
podOutboundPortExclusionList, _ := wh.getPortExclusionListForPod(pod, namespace, outboundPortExclusionListAnnotation)
globalOutboundPortExclusionList := wh.configurator.GetOutboundPortExclusionList()

outboundPortExclusionList := mergePortExclusionLists(podOutboundPortExclusionList, globalOutboundPortExclusionList)

// Build inbound port exclusion list
podInboundPortExclusionList, _ := wh.getPortExclusionListForPod(pod, namespace, inboundPortExclusionListAnnotation)
globalInboundPortExclusionList := wh.configurator.GetInboundPortExclusionList()
inboundPortExclusionList := mergePortExclusionLists(podInboundPortExclusionList, globalInboundPortExclusionList)

// Add the Init Container
initContainer := getInitContainerSpec(constants.InitContainerName, wh.configurator, wh.configurator.GetOutboundIPRangeExclusionList(), outboundPortExclusionList, wh.configurator.IsPrivilegedInitContainer())
initContainer := getInitContainerSpec(constants.InitContainerName, wh.configurator, wh.configurator.GetOutboundIPRangeExclusionList(), outboundPortExclusionList, inboundPortExclusionList, wh.configurator.IsPrivilegedInitContainer())
pod.Spec.InitContainers = append(pod.Spec.InitContainers, initContainer)

// Add the Envoy sidecar
Expand Down Expand Up @@ -102,22 +107,20 @@ func makePatches(req *admissionv1.AdmissionRequest, pod *corev1.Pod) []jsonpatch
return admissionResponse.Patches
}

func mergePortExclusionLists(podOutboundPortExclusionList, globalOutboundPortExclusionList []int) []int {
func mergePortExclusionLists(podSpecificPortExclusionList, globalPortExclusionList []int) []int {
portExclusionListMap := mapset.NewSet()
var portExclusionListMerged []int

// iterate over the global outbound ports to be excluded
for _, port := range globalOutboundPortExclusionList {
addedToSet := portExclusionListMap.Add(port)
if addedToSet {
for _, port := range globalPortExclusionList {
if addedToSet := portExclusionListMap.Add(port); addedToSet {
portExclusionListMerged = append(portExclusionListMerged, port)
}
}

// iterate over the pod level outbound ports to be excluded
for _, port := range podOutboundPortExclusionList {
addedToSet := portExclusionListMap.Add(port)
if addedToSet {
// iterate over the pod specific ports to be excluded
for _, port := range podSpecificPortExclusionList {
if addedToSet := portExclusionListMap.Add(port); addedToSet {
portExclusionListMerged = append(portExclusionListMerged, port)
}
}
Expand Down
1 change: 1 addition & 0 deletions pkg/injector/patch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ func TestCreatePatch(t *testing.T) {
mockConfigurator.EXPECT().IsPrivilegedInitContainer().Return(false).Times(1)
mockConfigurator.EXPECT().GetOutboundIPRangeExclusionList().Return(nil).Times(1)
mockConfigurator.EXPECT().GetOutboundPortExclusionList().Return(nil).Times(1)
mockConfigurator.EXPECT().GetInboundPortExclusionList().Return(nil).Times(1)
mockConfigurator.EXPECT().GetProxyResources().Return(corev1.ResourceRequirements{}).Times(1)

pod := tests.NewPodFixture(namespace, podName, tests.BookstoreServiceAccountName, nil)
Expand Down
Loading