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

Commit

Permalink
Merge pull request #2580 from ksubrmnn/priv_init
Browse files Browse the repository at this point in the history
feat(install): Enable optional privileged containers
  • Loading branch information
ksubrmnn authored Feb 24, 2021
2 parents abdf680 + 4c1cc44 commit aad5cc9
Show file tree
Hide file tree
Showing 16 changed files with 114 additions and 38 deletions.
1 change: 1 addition & 0 deletions charts/osm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ The following table lists the configurable parameters of the osm chart and their
| OpenServiceMesh.enableEgress | bool | `false` | Enable egress in the mesh |
| OpenServiceMesh.enableFluentbit | bool | `false` | Enable Fluent Bit sidecar deployment |
| OpenServiceMesh.enablePermissiveTrafficPolicy | bool | `false` | Enable permissive traffic policy mode |
| OpenServiceMesh.enablePrivilegedInitContainer | bool | `false` | Run init container in privileged mode |
| OpenServiceMesh.enablePrometheusScraping | bool | `true` | Enable Prometheus metrics scraping on sidecar proxies |
| OpenServiceMesh.enforceSingleMesh | bool | `false` | Enforce only deploying one mesh in the cluster |
| OpenServiceMesh.envoyLogLevel | string | `"error"` | Envoy log level is used to specify the level of logs collected from envoy |
Expand Down
1 change: 1 addition & 0 deletions charts/osm/templates/osm-configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ data:
permissive_traffic_policy_mode: {{ .Values.OpenServiceMesh.enablePermissiveTrafficPolicy | default "false" | quote }}
egress: {{ .Values.OpenServiceMesh.enableEgress | quote }}
envoy_log_level: {{ .Values.OpenServiceMesh.envoyLogLevel | quote }}
enable_privileged_init_container: {{ .Values.OpenServiceMesh.enablePrivilegedInitContainer | quote }}
enable_debug_server: {{ .Values.OpenServiceMesh.enableDebugServer | quote }}
prometheus_scraping: {{ .Values.OpenServiceMesh.enablePrometheusScraping | quote }}

Expand Down
12 changes: 11 additions & 1 deletion charts/osm/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"deployJaeger",
"tracing",
"webhookConfigNamePrefix",
"osmcontroller"
"osmcontroller",
"enablePrivilegedInitContainer"
],
"properties": {
"replicaCount": {
Expand Down Expand Up @@ -471,6 +472,15 @@
"examples": [
"osm-system"
]
},
"enablePrivilegedInitContainer": {
"$id": "#/properties/OpenServiceMesh/properties/enablePrivilegedInitContainer",
"type": "boolean",
"title": "The enablePrivilegedInitContainer schema",
"description": "Indicates whether the init container for pods in the mesh should be privileged",
"examples": [
false
]
}
},
"additionalProperties": true
Expand Down
3 changes: 3 additions & 0 deletions charts/osm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,6 @@ OpenServiceMesh:
requests:
cpu: "0.3"
memory: "64M"

# -- Run init container in privileged mode
enablePrivilegedInitContainer: false
1 change: 1 addition & 0 deletions docs/content/docs/osm_config_map.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ OSM deploys a configMap `osm-config` as a part of its control plane (in the same
| tracing_port| OpenServiceMesh.tracing.port | int | any non-zero integer value | `"9411"` | Port on which tracing is enabled. |
| use_https_ingress | OpenServiceMesh.useHTTPSIngress | bool | true, false | `"false"`| Enables HTTPS ingress on the mesh. |
| outbound_ip_range_exclusion_list | OpenServiceMesh.outboundIPRangeExclusionList | string | comma separated list of IP ranges of the form a.b.c.d/x | `-`| Global list of IP address ranges to exclude from outbound traffic interception by the sidecar proxy. |
| enable_privileged_init_container| OpenServiceMesh.enablePrivilegedInitContainer | bool | true, false | `"false"` | Enables privileged init containers for pods in mesh. When false, init containers only have NET_ADMIN |
6 changes: 6 additions & 0 deletions pkg/configurator/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ const (

// outboundIPRangeExclusionListKey is the key name used to specify the ip ranges to exclude from outbound sidecar interception
outboundIPRangeExclusionListKey = "outbound_ip_range_exclusion_list"

// enablePrivilegedInitContainer is the key name used to specify whether init containers should be privileged in the ConfigMap
enablePrivilegedInitContainer = "enable_privileged_init_container"
)

// NewConfigurator implements configurator.Configurator and creates the Kubernetes client to manage namespaces.
Expand Down Expand Up @@ -219,6 +222,8 @@ type osmConfig struct {

// OutboundIPRangeExclusionList is the list of outbound IP ranges to exclude from sidecar interception
OutboundIPRangeExclusionList string `yaml:"outbound_ip_range_exclusion_list"`

EnablePrivilegedInitContainer bool `yaml:"enable_privileged_init_container"`
}

func (c *Client) run(stop <-chan struct{}) {
Expand Down Expand Up @@ -271,6 +276,7 @@ func parseOSMConfigMap(configMap *v1.ConfigMap) *osmConfig {
osmConfigMap.EnvoyLogLevel, _ = GetStringValueForKey(configMap, envoyLogLevel)
osmConfigMap.ServiceCertValidityDuration, _ = GetStringValueForKey(configMap, serviceCertValidityDurationKey)
osmConfigMap.OutboundIPRangeExclusionList, _ = GetStringValueForKey(configMap, outboundIPRangeExclusionListKey)
osmConfigMap.EnablePrivilegedInitContainer, _ = GetBoolValueForKey(configMap, enablePrivilegedInitContainer)

if osmConfigMap.TracingEnable {
osmConfigMap.TracingAddress, _ = GetStringValueForKey(configMap, tracingAddressKey)
Expand Down
25 changes: 13 additions & 12 deletions pkg/configurator/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,19 @@ var _ = Describe("Test OSM ConfigMap parsing", func() {

It("Tag matches const key for all fields of OSM ConfigMap struct", func() {
fieldNameTag := map[string]string{
"PermissiveTrafficPolicyMode": PermissiveTrafficPolicyModeKey,
"Egress": egressKey,
"EnableDebugServer": enableDebugServer,
"PrometheusScraping": prometheusScrapingKey,
"TracingEnable": tracingEnableKey,
"TracingAddress": tracingAddressKey,
"TracingPort": tracingPortKey,
"TracingEndpoint": tracingEndpointKey,
"UseHTTPSIngress": useHTTPSIngressKey,
"EnvoyLogLevel": envoyLogLevel,
"ServiceCertValidityDuration": serviceCertValidityDurationKey,
"OutboundIPRangeExclusionList": outboundIPRangeExclusionListKey,
"PermissiveTrafficPolicyMode": PermissiveTrafficPolicyModeKey,
"Egress": egressKey,
"EnableDebugServer": enableDebugServer,
"PrometheusScraping": prometheusScrapingKey,
"TracingEnable": tracingEnableKey,
"TracingAddress": tracingAddressKey,
"TracingPort": tracingPortKey,
"TracingEndpoint": tracingEndpointKey,
"UseHTTPSIngress": useHTTPSIngressKey,
"EnvoyLogLevel": envoyLogLevel,
"ServiceCertValidityDuration": serviceCertValidityDurationKey,
"OutboundIPRangeExclusionList": outboundIPRangeExclusionListKey,
"EnablePrivilegedInitContainer": enablePrivilegedInitContainer,
}
t := reflect.TypeOf(osmConfig{})

Expand Down
5 changes: 5 additions & 0 deletions pkg/configurator/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,8 @@ func (c *Client) GetOutboundIPRangeExclusionList() []string {

return exclusionList
}

// IsPrivilegedInitContainer returns whether init containers should be privileged
func (c *Client) IsPrivilegedInitContainer() bool {
return c.getConfigMap().EnablePrivilegedInitContainer
}
17 changes: 15 additions & 2 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 @@ -65,4 +65,7 @@ type Configurator interface {

// GetOutboundIPRangeExclusionList returns the list of IP ranges of the form x.x.x.x/y to exclude from outbound sidecar interception
GetOutboundIPRangeExclusionList() []string

// IsPrivilegedInitContainer determines whether init containers should be privileged
IsPrivilegedInitContainer() bool
}
4 changes: 2 additions & 2 deletions pkg/configurator/validating_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ var (
deserializer = codecs.UniversalDeserializer()

// boolFields are the fields in osm-config that take in a boolean
boolFields = []string{"egress", "enable_debug_server", "permissive_traffic_policy_mode", "prometheus_scraping", "tracing_enable", "use_https_ingress"}
boolFields = []string{"egress", "enable_debug_server", "permissive_traffic_policy_mode", "prometheus_scraping", "tracing_enable", "use_https_ingress", "enable_privileged_init_container"}

// ValidEnvoyLogLevels is a list of envoy log levels
ValidEnvoyLogLevels = []string{"trace", "debug", "info", "warning", "warn", "error", "critical", "off"}

// defaultFields are the default fields in osm-config
defaultFields = []string{"egress", "enable_debug_server", "permissive_traffic_policy_mode", "prometheus_scraping", "use_https_ingress", "envoy_log_level", "service_cert_validity_duration", "tracing_enable"}
defaultFields = []string{"egress", "enable_debug_server", "permissive_traffic_policy_mode", "prometheus_scraping", "use_https_ingress", "envoy_log_level", "service_cert_validity_duration", "tracing_enable", "enable_privileged_init_container"}
)

const (
Expand Down
23 changes: 12 additions & 11 deletions pkg/configurator/validating_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,17 +203,18 @@ func TestCheckDefaultFields(t *testing.T) {
testName: "Contains all default fields",
configMap: corev1.ConfigMap{
Data: map[string]string{
"egress": "",
"enable_debug_server": "",
"permissive_traffic_policy_mode": "",
"prometheus_scraping": "",
"tracing_enable": "",
"use_https_ingress": "",
"envoy_log_level": "",
"service_cert_validity_duration": "",
"tracing_address": "",
"tracing_port": "",
"tracing_endpoint": "",
"egress": "",
"enable_debug_server": "",
"permissive_traffic_policy_mode": "",
"prometheus_scraping": "",
"tracing_enable": "",
"use_https_ingress": "",
"envoy_log_level": "",
"service_cert_validity_duration": "",
"tracing_address": "",
"tracing_port": "",
"tracing_endpoint": "",
"enable_privileged_init_container": "",
},
},
expRes: &v1beta1.AdmissionResponse{
Expand Down
3 changes: 2 additions & 1 deletion pkg/injector/init_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import (
corev1 "k8s.io/api/core/v1"
)

func getInitContainerSpec(containerName string, containerImage string, outboundIPRangeExclusionList []string) corev1.Container {
func getInitContainerSpec(containerName string, containerImage string, outboundIPRangeExclusionList []string, enablePrivilegedInitContainer bool) corev1.Container {
iptablesInitCommandsList := generateIptablesCommands(outboundIPRangeExclusionList)
iptablesInitCommand := strings.Join(iptablesInitCommandsList, " && ")

return corev1.Container{
Name: containerName,
Image: containerImage,
SecurityContext: &corev1.SecurityContext{
Privileged: &enablePrivilegedInitContainer,
Capabilities: &corev1.Capabilities{
Add: []corev1.Capability{
"NET_ADMIN",
Expand Down
45 changes: 37 additions & 8 deletions pkg/injector/init_container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,19 @@ func TestGetInitContainerSpec(t *testing.T) {
containerName := "-container-name-"
containerImage := "-init-container-image-"

privilegedFalse := false
privilegedTrue := true

testCases := []struct {
name string
outboundIPRangeExclusionList []string

expectedSpec v1.Container
privileged bool
expectedSpec v1.Container
}{
{
name: "init container without outbound exclusion list",
outboundIPRangeExclusionList: nil,

privileged: privilegedFalse,
expectedSpec: v1.Container{
Name: "-container-name-",
Image: "-init-container-image-",
Expand All @@ -40,18 +43,17 @@ func TestGetInitContainerSpec(t *testing.T) {
"NET_ADMIN",
},
},
Privileged: nil,
Privileged: &privilegedFalse,
},
Stdin: false,
StdinOnce: false,
TTY: false,
},
},

{
name: "init container with outbound exclusion list",
outboundIPRangeExclusionList: []string{"1.1.1.1/32", "10.0.0.10/24"},

privileged: privilegedFalse,
expectedSpec: v1.Container{
Name: "-container-name-",
Image: "-init-container-image-",
Expand All @@ -68,7 +70,34 @@ func TestGetInitContainerSpec(t *testing.T) {
"NET_ADMIN",
},
},
Privileged: nil,
Privileged: &privilegedFalse,
},
Stdin: false,
StdinOnce: false,
TTY: false,
},
},
{
name: "init container with privileged true",
outboundIPRangeExclusionList: nil,
privileged: privilegedTrue,
expectedSpec: v1.Container{
Name: "-container-name-",
Image: "-init-container-image-",
Command: []string{"/bin/sh"},
Args: []string{
"-c",
"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",
},
WorkingDir: "",
Resources: v1.ResourceRequirements{},
SecurityContext: &v1.SecurityContext{
Capabilities: &v1.Capabilities{
Add: []v1.Capability{
"NET_ADMIN",
},
},
Privileged: &privilegedTrue,
},
Stdin: false,
StdinOnce: false,
Expand All @@ -79,7 +108,7 @@ func TestGetInitContainerSpec(t *testing.T) {

for i, tc := range testCases {
t.Run(fmt.Sprintf("Testing test case %d: %s", i, tc.name), func(t *testing.T) {
actual := getInitContainerSpec(containerName, containerImage, tc.outboundIPRangeExclusionList)
actual := getInitContainerSpec(containerName, containerImage, tc.outboundIPRangeExclusionList, tc.privileged)
assert.Equal(tc.expectedSpec, actual)
})
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/injector/patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (wh *mutatingWebhook) createPatch(pod *corev1.Pod, req *v1beta1.AdmissionRe
pod.Spec.Volumes = append(pod.Spec.Volumes, getVolumeSpec(envoyBootstrapConfigName)...)

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

// Add the Envoy sidecar
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 @@ -56,6 +56,7 @@ var _ = Describe("Test all patch operations", func() {
pod := tests.NewPodFixture(namespace, podName, tests.BookstoreServiceAccountName, nil)
pod.Annotations = nil
mockConfigurator.EXPECT().GetEnvoyLogLevel().Return("").Times(1)
mockConfigurator.EXPECT().IsPrivilegedInitContainer().Return(false).Times(1)
mockConfigurator.EXPECT().GetOutboundIPRangeExclusionList().Return(nil).Times(1)

req := &v1beta1.AdmissionRequest{Namespace: namespace}
Expand Down

0 comments on commit aad5cc9

Please sign in to comment.