Skip to content

Commit 57fbf06

Browse files
Merge pull request #3521 from pacevedom/USHIFT-3473
USHIFT-3473: Add validations for network ipv4/ipv6 stacks
2 parents c57af7d + 6b4e556 commit 57fbf06

File tree

5 files changed

+198
-14
lines changed

5 files changed

+198
-14
lines changed

etcd/vendor/github.com/openshift/microshift/pkg/config/config.go

Lines changed: 55 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

etcd/vendor/github.com/openshift/microshift/pkg/config/network.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/config/config.go

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919

2020
"k8s.io/apimachinery/pkg/util/sets"
2121
"k8s.io/klog/v2"
22+
netutils "k8s.io/utils/net"
2223
"k8s.io/utils/ptr"
2324

2425
"github.com/apparentlymart/go-cidr/cidr"
@@ -301,6 +302,24 @@ func (c *Config) updateComputedValues() error {
301302
}
302303

303304
func (c *Config) validate() error {
305+
if !isValidIPAddress(c.ApiServer.AdvertiseAddress) {
306+
return fmt.Errorf("error validating apiServer.advertiseAddress (%q)", c.ApiServer.AdvertiseAddress)
307+
}
308+
if c.ApiServer.SkipInterface {
309+
err := checkAdvertiseAddressConfigured(c.ApiServer.AdvertiseAddress)
310+
if err != nil {
311+
return err
312+
}
313+
}
314+
315+
if !isValidIPAddress(c.Node.NodeIP) {
316+
return fmt.Errorf("error validating node.nodeIP (%q)", c.Node.NodeIP)
317+
}
318+
319+
if err := validateNetworkStack(c); err != nil {
320+
return fmt.Errorf("error validating networks: %w", err)
321+
}
322+
304323
//nolint:nestif // extracting the nested ifs will just increase the complexity of the if expressions as validation expands
305324
if len(c.ApiServer.SubjectAltNames) > 0 {
306325
// Any entry in SubjectAltNames will be included in the external access certificates.
@@ -353,13 +372,6 @@ func (c *Config) validate() error {
353372
)
354373
}
355374

356-
if c.ApiServer.SkipInterface {
357-
err := checkAdvertiseAddressConfigured(c.ApiServer.AdvertiseAddress)
358-
if err != nil {
359-
return err
360-
}
361-
}
362-
363375
switch c.Ingress.Status {
364376
case StatusManaged, StatusRemoved:
365377
default:
@@ -588,3 +600,39 @@ func validateAuditLogConfig(cfg AuditLog) error {
588600
}
589601
return errors.Join(errs...) // Join returns nil if len(errs) == 0
590602
}
603+
604+
func validateNetworkStack(cfg *Config) error {
605+
if len(cfg.Network.ClusterNetwork) != len(cfg.Network.ServiceNetwork) {
606+
return fmt.Errorf("network.serviceNetwork and network.clusterNetwork have different cardinality")
607+
}
608+
if len(cfg.Network.ServiceNetwork) > 2 {
609+
return fmt.Errorf("network.serviceNetwork can not have more than 2 entries")
610+
}
611+
ipv4Entries := 0
612+
ipv6Entries := 0
613+
for i := 0; i < len(cfg.Network.ClusterNetwork); i++ {
614+
_, _, err := net.ParseCIDR(cfg.Network.ServiceNetwork[i])
615+
if err != nil {
616+
return fmt.Errorf("invalid format in network.ServiceNetwork[%d]: %w", i, err)
617+
}
618+
_, _, err = net.ParseCIDR(cfg.Network.ClusterNetwork[i])
619+
if err != nil {
620+
return fmt.Errorf("invalid format in network.ClusterNetwork[%d]: %w", i, err)
621+
}
622+
if netutils.IPFamilyOfCIDRString(cfg.Network.ServiceNetwork[i]) != netutils.IPFamilyOfCIDRString(cfg.Network.ClusterNetwork[i]) {
623+
return fmt.Errorf("mismatched IP families in network.ServiceNetwork[%d] and network.ClusterNetwork[%d]", i, i)
624+
}
625+
if netutils.IPFamilyOfCIDRString(cfg.Network.ServiceNetwork[i]) == netutils.IPv4 {
626+
ipv4Entries++
627+
} else {
628+
ipv6Entries++
629+
}
630+
}
631+
if ipv4Entries > 1 || ipv6Entries > 1 {
632+
return fmt.Errorf("invalid number of entries of the same IP family in network.serviceNetwork and network.clusterNetwork")
633+
}
634+
if netutils.IPFamilyOfString(cfg.ApiServer.AdvertiseAddress) != netutils.IPFamilyOfCIDRString(cfg.Network.ServiceNetwork[0]) {
635+
return fmt.Errorf("invalid IP family in apiServer.AdvertiseAddress: does not match first network.ServiceNetwork IP family")
636+
}
637+
return nil
638+
}

pkg/config/config_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,84 @@ func TestValidate(t *testing.T) {
529529
}(),
530530
expectErr: false,
531531
},
532+
{
533+
name: "network-too-many-entries",
534+
config: func() *Config {
535+
c := mkDefaultConfig()
536+
c.Network.ServiceNetwork = []string{"1.2.3.4/24", "::1/128", "5.6.7.8/24"}
537+
c.Network.ClusterNetwork = []string{"9.10.11.12/24", "::2/128", "13.14.15.16/24"}
538+
c.ApiServer.AdvertiseAddress = "17.18.19.20"
539+
return c
540+
}(),
541+
expectErr: true,
542+
},
543+
{
544+
name: "network-same-ip-family-ipv4",
545+
config: func() *Config {
546+
c := mkDefaultConfig()
547+
c.Network.ServiceNetwork = []string{"21.22.23.24/24", "25.26.27.28/24"}
548+
c.Network.ClusterNetwork = []string{"29.30.31.32/24", "33.34.35.36/24"}
549+
c.ApiServer.AdvertiseAddress = "37.38.39.40"
550+
return c
551+
}(),
552+
expectErr: true,
553+
},
554+
{
555+
name: "network-same-ip-family-ipv6",
556+
config: func() *Config {
557+
c := mkDefaultConfig()
558+
c.Network.ServiceNetwork = []string{"fd01::/64", "fd02::/64"}
559+
c.Network.ClusterNetwork = []string{"fd03::/64", "fd04::/64"}
560+
c.ApiServer.AdvertiseAddress = "fd01::1"
561+
return c
562+
}(),
563+
expectErr: true,
564+
},
565+
{
566+
name: "network-bad-format-ipv4",
567+
config: func() *Config {
568+
c := mkDefaultConfig()
569+
c.Network.ServiceNetwork = []string{"1.2.3.300/24"}
570+
c.Network.ClusterNetwork = []string{"300.1.2.3/24"}
571+
c.ApiServer.AdvertiseAddress = "8.8.8.8"
572+
return c
573+
}(),
574+
expectErr: true,
575+
},
576+
{
577+
name: "network-bad-format-ipv6",
578+
config: func() *Config {
579+
c := mkDefaultConfig()
580+
c.Network.ServiceNetwork = []string{"fd01:::/64"}
581+
c.Network.ClusterNetwork = []string{"fd05::/64"}
582+
c.ApiServer.AdvertiseAddress = "fd01::2"
583+
return c
584+
}(),
585+
expectErr: true,
586+
},
587+
{
588+
name: "network-different-ip-family",
589+
config: func() *Config {
590+
c := mkDefaultConfig()
591+
c.Network.ServiceNetwork = []string{"fd05::/64"}
592+
c.Network.ClusterNetwork = []string{"4.3.2.1/24"}
593+
c.ApiServer.AdvertiseAddress = "fd01::3"
594+
return c
595+
}(),
596+
expectErr: true,
597+
},
598+
599+
{
600+
name: "network-different-ip-family-advertise-address",
601+
config: func() *Config {
602+
c := mkDefaultConfig()
603+
c.Network.ServiceNetwork = []string{"fd06::/64"}
604+
c.Network.ClusterNetwork = []string{"fd07::/64"}
605+
c.ApiServer.AdvertiseAddress = "10.20.30.40"
606+
return c
607+
}(),
608+
expectErr: true,
609+
},
532610
}
533611
for _, tt := range ttests {
534612
t.Run(tt.name, func(t *testing.T) {

pkg/config/network.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,8 @@ func getClusterDNS(serviceCIDR string) (string, error) {
5858

5959
return dnsClusterIP.String(), nil
6060
}
61+
62+
func isValidIPAddress(ipAddress string) bool {
63+
ip := net.ParseIP(ipAddress)
64+
return ip != nil
65+
}

0 commit comments

Comments
 (0)