From 682432660e017f7f27ad2e6cf89d858801b508df Mon Sep 17 00:00:00 2001 From: Tom Wieczorek Date: Tue, 12 Nov 2024 17:43:45 +0100 Subject: [PATCH] Correctly detect DNS address computation errors The existing code is unable to compute meaningful DNS addresses if the service CIDR doesn't describe a v4 network. Error out whenever the network IP is not a v4 address until it is clear how to properly compute the DNS address for a v6 network. Also, copy `address` by value so that changes to it don't change `ipnet` as well. Signed-off-by: Tom Wieczorek --- pkg/apis/k0s/v1beta1/network.go | 15 +++++++++++---- pkg/apis/k0s/v1beta1/network_test.go | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/pkg/apis/k0s/v1beta1/network.go b/pkg/apis/k0s/v1beta1/network.go index 3757f5e5591a..893b4b84e98b 100644 --- a/pkg/apis/k0s/v1beta1/network.go +++ b/pkg/apis/k0s/v1beta1/network.go @@ -18,8 +18,10 @@ package v1beta1 import ( "encoding/json" + "errors" "fmt" "net" + "slices" "k8s.io/apimachinery/pkg/util/validation/field" utilnet "k8s.io/utils/net" @@ -135,9 +137,14 @@ func (n *Network) DNSAddress() (string, error) { return "", fmt.Errorf("failed to parse service CIDR %q: %w", n.ServiceCIDR, err) } - address := ipnet.IP.To4() - if IsIPv6String(ipnet.IP.String()) { - address = ipnet.IP.To16() + address := slices.Clone(ipnet.IP.To4()) + if address == nil { + // The network address is not an IPv4 address. This can only happen if + // k0s is running in IPv6-only mode, which is currently not a supported + // configuration. In dual-stack mode, the IPv6 CIDR is stored in + // n.DualStack.IPv6ServiceCIDR. Error out until it is clear how to + // properly calculate the DNS address for a v6 network. + return "", fmt.Errorf("%w: DNS address calculation for non-v4 CIDR: %s", errors.ErrUnsupported, n.ServiceCIDR) } prefixlen, _ := ipnet.Mask.Size() @@ -148,7 +155,7 @@ func (n *Network) DNSAddress() (string, error) { } if !ipnet.Contains(address) { - return "", fmt.Errorf("failed to calculate a valid DNS address: %q", address.String()) + return "", fmt.Errorf("failed to calculate DNS address: CIDR too narrow: %s", n.ServiceCIDR) } return address.String(), nil diff --git a/pkg/apis/k0s/v1beta1/network_test.go b/pkg/apis/k0s/v1beta1/network_test.go index a3ddd47e9bbb..3b30bf8263b1 100644 --- a/pkg/apis/k0s/v1beta1/network_test.go +++ b/pkg/apis/k0s/v1beta1/network_test.go @@ -17,6 +17,7 @@ limitations under the License. package v1beta1 import ( + "errors" "testing" "k8s.io/utils/ptr" @@ -42,6 +43,19 @@ func (s *NetworkSuite) TestAddresses() { s.Require().NoError(err) s.Equal("10.96.0.250", dns) }) + s.Run("DNS_service_cidr_too_narrow", func() { + n := Network{ServiceCIDR: "192.168.178.0/31"} + dns, err := n.DNSAddress() + s.Zero(dns) + s.ErrorContains(err, "failed to calculate DNS address: CIDR too narrow: 192.168.178.0/31") + }) + s.Run("DNS_rejects_v6_service_cidr", func() { + n := Network{ServiceCIDR: "fd00:abcd:1234::/64"} + dns, err := n.DNSAddress() + s.Zero(dns) + s.ErrorIs(err, errors.ErrUnsupported) + s.ErrorContains(err, "unsupported operation: DNS address calculation for non-v4 CIDR: fd00:abcd:1234::/64") + }) s.Run("Internal_api_address_default", func() { n := DefaultNetwork() api, err := n.InternalAPIAddresses()