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]>
(cherry picked from commit 6824326)
(cherry picked from commit de30711)
  • Loading branch information
twz123 committed Nov 25, 2024
1 parent 05d77a0 commit 33d63d7
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 @@ -129,9 +131,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 @@ -142,7 +149,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"

"github.com/stretchr/testify/suite"
Expand All @@ -40,6 +41,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.T().Run("Internal_api_address_default", func(t *testing.T) {
n := DefaultNetwork()
api, err := n.InternalAPIAddresses()
Expand Down

0 comments on commit 33d63d7

Please sign in to comment.