talos/internal/integration/api/firewall.go
Dmitriy Matrenichev fa3b933705
chore: replace fmt.Errorf with errors.New where possible
This time use `eg` from `x/tools` repo tool to do this.

Signed-off-by: Dmitriy Matrenichev <dmitry.matrenichev@siderolabs.com>
2024-02-14 17:39:30 +03:00

121 lines
2.9 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//go:build integration_api
package api
import (
"context"
"crypto/tls"
"errors"
"fmt"
"net"
"net/http"
"os"
"strconv"
"time"
"github.com/cosi-project/runtime/pkg/safe"
"github.com/hashicorp/go-cleanhttp"
"golang.org/x/sync/errgroup"
"github.com/siderolabs/talos/internal/integration/base"
"github.com/siderolabs/talos/pkg/machinery/client"
"github.com/siderolabs/talos/pkg/machinery/constants"
"github.com/siderolabs/talos/pkg/machinery/resources/network"
)
// FirewallSuite ...
type FirewallSuite struct {
base.APISuite
ctx context.Context //nolint:containedctx
ctxCancel context.CancelFunc
}
// SuiteName ...
func (suite *FirewallSuite) SuiteName() string {
return "api.FirewallSuite"
}
// SetupTest ...
func (suite *FirewallSuite) SetupTest() {
if suite.Cluster == nil {
suite.T().Skip("without full cluster state can't guarantee availability of kubelet IPs")
}
// make sure we abort at some point in time, but give enough room for Resets
suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), 30*time.Second)
}
// TearDownTest ...
func (suite *FirewallSuite) TearDownTest() {
if suite.ctxCancel != nil {
suite.ctxCancel()
}
}
// TestKubeletAccess verifies that without firewall kubelet API is available, and not available otherwise.
func (suite *FirewallSuite) TestKubeletAccess() {
allNodes := suite.DiscoverNodeInternalIPs(suite.ctx)
_, err := safe.StateGetByID[*network.NfTablesChain](client.WithNode(suite.ctx, allNodes[0]), suite.Client.COSI, "ingress")
firewallEnabled := err == nil
eg, ctx := errgroup.WithContext(suite.ctx)
transport := cleanhttp.DefaultTransport()
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
client := http.Client{
Transport: transport,
}
for _, node := range allNodes {
node := node
eg.Go(func() error {
attemptCtx, cancel := context.WithTimeout(ctx, time.Second)
defer cancel()
req, err := http.NewRequestWithContext(
attemptCtx,
http.MethodGet,
fmt.Sprintf("https://%s/healthz", net.JoinHostPort(node, strconv.Itoa(constants.KubeletPort))),
nil,
)
if err != nil {
return err
}
resp, err := client.Do(req)
if resp != nil {
resp.Body.Close() //nolint:errcheck
}
if firewallEnabled {
if err == nil {
return errors.New("kubelet API should not be available")
}
if !errors.Is(err, os.ErrDeadlineExceeded) && !errors.Is(err, context.DeadlineExceeded) {
return fmt.Errorf("unexpected error: %w", err)
}
} else if err != nil {
return fmt.Errorf("kubelet API should be available: %w", err)
}
return nil
})
}
suite.Require().NoError(eg.Wait())
}
func init() {
allSuites = append(allSuites, new(FirewallSuite))
}