Skip to content

Commit

Permalink
Correctly detect DNS address computation errors
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
twz123 committed Nov 12, 2024
1 parent e331fe2 commit 6824326
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 4 deletions.
15 changes: 11 additions & 4 deletions pkg/apis/k0s/v1beta1/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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()
Expand All @@ -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
Expand Down
14 changes: 14 additions & 0 deletions pkg/apis/k0s/v1beta1/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package v1beta1

import (
"errors"
"testing"

"k8s.io/utils/ptr"
Expand All @@ -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()
Expand Down

0 comments on commit 6824326

Please sign in to comment.