Skip to content

Commit b01c2c4

Browse files
committed
Use a naive approach to parse port before env var expansion
1 parent 95ca52c commit b01c2c4

File tree

4 files changed

+54
-5
lines changed

4 files changed

+54
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
2+
change_type: bug_fix
3+
4+
# The name of the component, or a single word describing the area of concern, (e.g. collector, target allocator, auto-instrumentation, opamp, github action)
5+
component: operator
6+
7+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
8+
note: Fix the admission webhook to when metrics service address host uses env var expansion
9+
10+
# One or more tracking issues related to the change
11+
issues: [3513]
12+
13+
# (Optional) One or more lines of additional information to render under the primary note.
14+
# These lines will be padded with 2 spaces and then inserted directly into the document.
15+
# Use pipe (|) for multiline entries.
16+
subtext: |
17+
This should allow the metrics service address to have the host portion expanded from an environment variable,
18+
like `$(env:POD_IP)` instead of using `0.0.0.0`, which is the [recommended by the Collector](https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/security-best-practices.md#safeguards-against-denial-of-service-attacks).

apis/v1beta1/collector_webhook_test.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,17 @@ func TestOTELColValidatingWebhook(t *testing.T) {
588588
five := int32(5)
589589
maxInt := int32(math.MaxInt32)
590590

591-
cfg := v1beta1.Config{}
591+
cfg := v1beta1.Config{
592+
Service: v1beta1.Service{
593+
Telemetry: &v1beta1.AnyConfig{
594+
Object: map[string]interface{}{
595+
"metrics": map[string]interface{}{
596+
"address": "${env:POD_ID}:8888",
597+
},
598+
},
599+
},
600+
},
601+
}
592602
err := yaml.Unmarshal([]byte(cfgYaml), &cfg)
593603
require.NoError(t, err)
594604

apis/v1beta1/config.go

+24-2
Original file line numberDiff line numberDiff line change
@@ -427,16 +427,18 @@ type Service struct {
427427
Pipelines map[string]*Pipeline `json:"pipelines" yaml:"pipelines"`
428428
}
429429

430+
const defaultServicePort int32 = 8888
431+
430432
// MetricsEndpoint gets the port number and host address for the metrics endpoint from the collector config if it has been set.
431433
func (s *Service) MetricsEndpoint() (string, int32, error) {
432434
defaultAddr := "0.0.0.0"
433435
if s.GetTelemetry() == nil {
434436
// telemetry isn't set, use the default
435-
return defaultAddr, 8888, nil
437+
return defaultAddr, defaultServicePort, nil
436438
}
437439
host, port, netErr := net.SplitHostPort(s.GetTelemetry().Metrics.Address)
438440
if netErr != nil && strings.Contains(netErr.Error(), "missing port in address") {
439-
return defaultAddr, 8888, nil
441+
return defaultAddr, defaultServicePort, nil
440442
} else if netErr != nil {
441443
return "", 0, netErr
442444
}
@@ -452,6 +454,26 @@ func (s *Service) MetricsEndpoint() (string, int32, error) {
452454
return host, int32(i64), nil
453455
}
454456

457+
// NaivePort attempts gets the port number from the host address without doing any validation regarding the address itself.
458+
// It works even before env var expansion happens, when a simple `net.SplitHostPort` would fail because of the extra colon
459+
// from the env var, i.e. the address looks like "${env:POD_IP}:4317" or "${env:POD_IP}".
460+
// It does not work in cases which the port itself is a variable, i.e. "${env:POD_IP}:${env:PORT}".
461+
func (s *Service) NaivePort() (int32, error) {
462+
telemetry := s.GetTelemetry()
463+
if telemetry == nil {
464+
return defaultServicePort, nil
465+
}
466+
splitAddress := strings.Split(telemetry.Metrics.Address, ":")
467+
if len(splitAddress) == 1 {
468+
return defaultServicePort, nil
469+
}
470+
port, err := strconv.Atoi(splitAddress[len(splitAddress)-1])
471+
if err != nil {
472+
return 0, err
473+
}
474+
return int32(port), nil
475+
}
476+
455477
// ApplyDefaults inserts configuration defaults if it has not been set.
456478
func (s *Service) ApplyDefaults() error {
457479
telemetryAddr, telemetryPort, err := s.MetricsEndpoint()

internal/manifests/collector/service.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ func HeadlessService(params manifests.Params) (*corev1.Service, error) {
7373
}
7474

7575
func MonitoringService(params manifests.Params) (*corev1.Service, error) {
76-
7776
name := naming.MonitoringService(params.OtelCol.Name)
7877
labels := manifestutils.Labels(params.OtelCol.ObjectMeta, name, params.OtelCol.Spec.Image, ComponentOpenTelemetryCollector, []string{})
7978
labels[monitoringLabel] = valueExists
@@ -84,7 +83,7 @@ func MonitoringService(params manifests.Params) (*corev1.Service, error) {
8483
return nil, err
8584
}
8685

87-
_, metricsPort, err := params.OtelCol.Spec.Config.Service.MetricsEndpoint()
86+
metricsPort, err := params.OtelCol.Spec.Config.Service.NaivePort()
8887
if err != nil {
8988
return nil, err
9089
}

0 commit comments

Comments
 (0)