Skip to content

Commit a68c154

Browse files
authored
Add unprivileged port validation (#7034)
1 parent 774c192 commit a68c154

File tree

5 files changed

+47
-45
lines changed

5 files changed

+47
-45
lines changed

cmd/nginx-ingress/flags.go

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"regexp"
1010
"strings"
1111

12+
internalValidation "github.com/nginxinc/kubernetes-ingress/internal/validation"
1213
api_v1 "k8s.io/api/core/v1"
1314
"k8s.io/apimachinery/pkg/labels"
1415
"k8s.io/apimachinery/pkg/util/validation"
@@ -345,22 +346,22 @@ func mustValidateFlags(ctx context.Context) {
345346
nl.Fatalf(l, "Invalid value for leader-election-lock-name: %v", statusLockNameValidationError)
346347
}
347348

348-
statusPortValidationError := validatePort(*nginxStatusPort)
349+
statusPortValidationError := internalValidation.ValidateUnprivilegedPort(*nginxStatusPort)
349350
if statusPortValidationError != nil {
350351
nl.Fatalf(l, "Invalid value for nginx-status-port: %v", statusPortValidationError)
351352
}
352353

353-
metricsPortValidationError := validatePort(*prometheusMetricsListenPort)
354+
metricsPortValidationError := internalValidation.ValidateUnprivilegedPort(*prometheusMetricsListenPort)
354355
if metricsPortValidationError != nil {
355356
nl.Fatalf(l, "Invalid value for prometheus-metrics-listen-port: %v", metricsPortValidationError)
356357
}
357358

358-
readyStatusPortValidationError := validatePort(*readyStatusPort)
359+
readyStatusPortValidationError := internalValidation.ValidateUnprivilegedPort(*readyStatusPort)
359360
if readyStatusPortValidationError != nil {
360361
nl.Fatalf(l, "Invalid value for ready-status-port: %v", readyStatusPortValidationError)
361362
}
362363

363-
healthProbePortValidationError := validatePort(*serviceInsightListenPort)
364+
healthProbePortValidationError := internalValidation.ValidateUnprivilegedPort(*serviceInsightListenPort)
364365
if healthProbePortValidationError != nil {
365366
nl.Fatalf(l, "Invalid value for service-insight-listen-port: %v", metricsPortValidationError)
366367
}
@@ -464,14 +465,6 @@ func validateResourceName(name string) error {
464465
return nil
465466
}
466467

467-
// validatePort makes sure a given port is inside the valid port range for its usage
468-
func validatePort(port int) error {
469-
if port < 1024 || port > 65535 {
470-
return fmt.Errorf("port outside of valid port range [1024 - 65535]: %v", port)
471-
}
472-
return nil
473-
}
474-
475468
// validateLogLevel makes sure a given logLevel is one of the allowed values
476469
func validateLogLevel(logLevel string) error {
477470
switch strings.ToLower(logLevel) {

cmd/nginx-ingress/flags_test.go

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,6 @@ import (
77
"testing"
88
)
99

10-
func TestValidatePort(t *testing.T) {
11-
badPorts := []int{80, 443, 1, 1023, 65536}
12-
for _, badPort := range badPorts {
13-
err := validatePort(badPort)
14-
if err == nil {
15-
t.Errorf("Expected error for port %v\n", badPort)
16-
}
17-
}
18-
19-
goodPorts := []int{8080, 8081, 8082, 1024, 65535}
20-
for _, goodPort := range goodPorts {
21-
err := validatePort(goodPort)
22-
if err != nil {
23-
t.Errorf("Error for valid port: %v err: %v\n", goodPort, err)
24-
}
25-
}
26-
}
27-
2810
func TestParseNginxStatusAllowCIDRs(t *testing.T) {
2911
badCIDRs := []struct {
3012
input string

internal/validation/validation.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@ var (
1414
)
1515

1616
// ValidatePort ensure port matches rfc6335 https://www.rfc-editor.org/rfc/rfc6335.html
17-
func ValidatePort(value string) error {
18-
port, err := strconv.Atoi(value)
19-
if err != nil {
20-
return fmt.Errorf("error parsing port number: %w", err)
17+
func ValidatePort(value int) error {
18+
if value > 65535 || value < 1 {
19+
return fmt.Errorf("error parsing port: %d not a valid port number", value)
2120
}
22-
if port > 65535 || port < 1 {
23-
return fmt.Errorf("error parsing port: %v not a valid port number", port)
21+
return nil
22+
}
23+
24+
// ValidateUnprivilegedPort ensure port is in the 1024-65535 range
25+
func ValidateUnprivilegedPort(value int) error {
26+
if value > 65535 || value < 1023 {
27+
return fmt.Errorf("port outside of valid port range [1024 - 65535]: %d", value)
2428
}
2529
return nil
2630
}
@@ -34,7 +38,11 @@ func ValidateHost(host string) error {
3438
if validIPRegex.MatchString(host) || validDNSRegex.MatchString(host) || validHostnameRegex.MatchString(host) {
3539
chunks := strings.Split(host, ":")
3640
if len(chunks) > 1 {
37-
err := ValidatePort(chunks[1])
41+
port, err := strconv.Atoi(chunks[1])
42+
if err != nil {
43+
return err
44+
}
45+
err = ValidatePort(port)
3846
if err != nil {
3947
return fmt.Errorf("invalid port: %w", err)
4048
}

internal/validation/validation_test.go

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,42 @@ import (
88
func TestValidatePort_IsValidOnValidInput(t *testing.T) {
99
t.Parallel()
1010

11-
ports := []string{"1", "65535"}
11+
ports := []int{1, 65535}
1212
for _, p := range ports {
1313
if err := ValidatePort(p); err != nil {
1414
t.Error(err)
1515
}
1616
}
1717
}
1818

19-
func TestValidatePort_ErrorsOnInvalidString(t *testing.T) {
19+
func TestValidatePort_ErrorsOnInvalidRange(t *testing.T) {
2020
t.Parallel()
2121

22-
if err := ValidatePort(""); err == nil {
23-
t.Error("want error, got nil")
22+
ports := []int{0, -1, 65536}
23+
for _, p := range ports {
24+
if err := ValidatePort(p); err == nil {
25+
t.Error("want error, got nil")
26+
}
2427
}
2528
}
2629

27-
func TestValidatePort_ErrorsOnInvalidRange(t *testing.T) {
30+
func TestValidateUnprivilegedPort_IsValidOnValidInput(t *testing.T) {
2831
t.Parallel()
2932

30-
ports := []string{"0", "-1", "65536"}
33+
ports := []int{1024, 65535}
3134
for _, p := range ports {
32-
if err := ValidatePort(p); err == nil {
35+
if err := ValidateUnprivilegedPort(p); err != nil {
36+
t.Error(err)
37+
}
38+
}
39+
}
40+
41+
func TestValidateUnprivilegedPort_ErrorsOnInvalidRange(t *testing.T) {
42+
t.Parallel()
43+
44+
ports := []int{0, -1, 80, 443, 65536}
45+
for _, p := range ports {
46+
if err := ValidateUnprivilegedPort(p); err == nil {
3347
t.Error("want error, got nil")
3448
}
3549
}

pkg/apis/dos/validation/dos.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"net"
66
"net/url"
77
"regexp"
8+
"strconv"
89
"strings"
910

1011
internalValidation "github.com/nginxinc/kubernetes-ingress/internal/validation"
@@ -128,7 +129,11 @@ func validateAppProtectDosLogDest(dstAntn string) error {
128129
}
129130
if validIPRegex.MatchString(dstAntn) || validDNSRegex.MatchString(dstAntn) || validLocalhostRegex.MatchString(dstAntn) {
130131
chunks := strings.Split(dstAntn, ":")
131-
err := internalValidation.ValidatePort(chunks[1])
132+
port, err := strconv.Atoi(chunks[1])
133+
if err != nil {
134+
return err
135+
}
136+
err = internalValidation.ValidatePort(port)
132137
if err != nil {
133138
return fmt.Errorf("invalid log destination: %w", err)
134139
}

0 commit comments

Comments
 (0)