Skip to content

Commit d321ac5

Browse files
committed
refactor: migrate node e2e tests off insecure port
Signed-off-by: knight42 <[email protected]>
1 parent 2046f42 commit d321ac5

File tree

9 files changed

+132
-36
lines changed

9 files changed

+132
-36
lines changed

test/e2e/framework/kubelet/config.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,21 @@ func pollConfigz(timeout time.Duration, pollInterval time.Duration, nodeName, na
7575
framework.Logf("http requesting node kubelet /configz")
7676
endpoint = fmt.Sprintf("http://127.0.0.1:%d/api/v1/nodes/%s/proxy/configz", port, nodeName)
7777
} else {
78-
endpoint = fmt.Sprintf("http://127.0.0.1:8080/api/v1/nodes/%s/proxy/configz", framework.TestContext.NodeName)
78+
endpoint = fmt.Sprintf("%s/api/v1/nodes/%s/proxy/configz", framework.TestContext.Host, framework.TestContext.NodeName)
7979
}
8080
tr := &http.Transport{
8181
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
8282
}
8383
client := &http.Client{Transport: tr}
8484
req, err := http.NewRequest("GET", endpoint, nil)
8585
framework.ExpectNoError(err)
86+
if !useProxy {
87+
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", framework.TestContext.BearerToken))
88+
}
8689
req.Header.Add("Accept", "application/json")
8790

8891
var resp *http.Response
89-
wait.PollImmediate(pollInterval, timeout, func() (bool, error) {
92+
err = wait.PollImmediate(pollInterval, timeout, func() (bool, error) {
9093
resp, err = client.Do(req)
9194
if err != nil {
9295
framework.Logf("Failed to get /configz, retrying. Error: %v", err)
@@ -99,6 +102,7 @@ func pollConfigz(timeout time.Duration, pollInterval time.Duration, nodeName, na
99102

100103
return true, nil
101104
})
105+
framework.ExpectNoError(err, "Failed to get successful response from /configz")
102106
return resp
103107
}
104108

test/e2e/framework/test_context.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ limitations under the License.
1717
package framework
1818

1919
import (
20+
"crypto/rand"
21+
"encoding/base64"
2022
"flag"
2123
"fmt"
2224
"io/ioutil"
25+
"math"
2326
"os"
2427
"sort"
2528
"strings"
@@ -32,11 +35,12 @@ import (
3235
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
3336
cliflag "k8s.io/component-base/cli/flag"
3437
"k8s.io/klog/v2"
38+
3539
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
3640
)
3741

3842
const (
39-
defaultHost = "http://127.0.0.1:8080"
43+
defaultHost = "https://127.0.0.1:6443"
4044

4145
// DefaultNumNodes is the number of nodes. If not specified, then number of nodes is auto-detected
4246
DefaultNumNodes = -1
@@ -77,6 +81,7 @@ type TestContextType struct {
7781
KubeVolumeDir string
7882
CertDir string
7983
Host string
84+
BearerToken string
8085
// TODO: Deprecating this over time... instead just use gobindata_util.go , see #23987.
8186
RepoRoot string
8287
DockershimCheckpointDir string
@@ -286,7 +291,7 @@ func RegisterCommonFlags(flags *flag.FlagSet) {
286291
flags.BoolVar(&TestContext.DeleteNamespaceOnFailure, "delete-namespace-on-failure", true, "If true, framework will delete test namespace on failure. Used only during test debugging.")
287292
flags.IntVar(&TestContext.AllowedNotReadyNodes, "allowed-not-ready-nodes", 0, "If non-zero, framework will allow for that many non-ready nodes when checking for all ready nodes.")
288293

289-
flags.StringVar(&TestContext.Host, "host", "", fmt.Sprintf("The host, or apiserver, to connect to. Will default to %s if this argument and --kubeconfig are not set", defaultHost))
294+
flags.StringVar(&TestContext.Host, "host", "", fmt.Sprintf("The host, or apiserver, to connect to. Will default to %s if this argument and --kubeconfig are not set.", defaultHost))
290295
flags.StringVar(&TestContext.ReportPrefix, "report-prefix", "", "Optional prefix for JUnit XML reports. Default is empty, which doesn't prepend anything to the default name.")
291296
flags.StringVar(&TestContext.ReportDir, "report-dir", "", "Path to the directory where the JUnit XML reports should be saved. Default is empty, which doesn't generate these reports.")
292297
flags.Var(cliflag.NewMapStringBool(&TestContext.FeatureGates), "feature-gates", "A set of key=value pairs that describe feature gates for alpha/experimental features.")
@@ -402,6 +407,18 @@ func createKubeConfig(clientCfg *restclient.Config) *clientcmdapi.Config {
402407
return configCmd
403408
}
404409

410+
func generateSecureToken(tokenLen int) (string, error) {
411+
// Number of bytes to be tokenLen when base64 encoded.
412+
tokenSize := math.Ceil(float64(tokenLen) * 6 / 8)
413+
rawToken := make([]byte, int(tokenSize))
414+
if _, err := rand.Read(rawToken); err != nil {
415+
return "", err
416+
}
417+
encoded := base64.RawURLEncoding.EncodeToString(rawToken)
418+
token := encoded[:tokenLen]
419+
return token, nil
420+
}
421+
405422
// AfterReadingAllFlags makes changes to the context after all flags
406423
// have been read.
407424
func AfterReadingAllFlags(t *TestContextType) {
@@ -421,6 +438,13 @@ func AfterReadingAllFlags(t *TestContextType) {
421438
t.Host = defaultHost
422439
}
423440
}
441+
if len(t.BearerToken) == 0 {
442+
var err error
443+
t.BearerToken, err = generateSecureToken(16)
444+
if err != nil {
445+
klog.Fatalf("Failed to generate bearer token: %v", err)
446+
}
447+
}
424448
// Allow 1% of nodes to be unready (statistically) - relevant for large clusters.
425449
if t.AllowedNotReadyNodes == 0 {
426450
t.AllowedNotReadyNodes = t.CloudConfig.NumNodes / 100

test/e2e/framework/util.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,13 @@ func LoadConfig() (config *restclient.Config, err error) {
467467

468468
if TestContext.NodeE2E {
469469
// This is a node e2e test, apply the node e2e configuration
470-
return &restclient.Config{Host: TestContext.Host}, nil
470+
return &restclient.Config{
471+
Host: TestContext.Host,
472+
BearerToken: TestContext.BearerToken,
473+
TLSClientConfig: restclient.TLSClientConfig{
474+
Insecure: true,
475+
},
476+
}, nil
471477
}
472478
c, err := restclientConfig(TestContext.KubeContext)
473479
if err != nil {

test/e2e_node/e2e_node_suite_test.go

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,21 @@ import (
5656
"k8s.io/klog/v2"
5757
)
5858

59-
var e2es *services.E2EServices
60-
61-
// TODO(random-liu): Change the following modes to sub-command.
62-
var runServicesMode = flag.Bool("run-services-mode", false, "If true, only run services (etcd, apiserver) in current process, and not run test.")
63-
var runKubeletMode = flag.Bool("run-kubelet-mode", false, "If true, only start kubelet, and not run test.")
64-
var systemValidateMode = flag.Bool("system-validate-mode", false, "If true, only run system validation in current process, and not run test.")
65-
var systemSpecFile = flag.String("system-spec-file", "", "The name of the system spec file that will be used for node conformance test. If it's unspecified or empty, the default system spec (system.DefaultSysSpec) will be used.")
59+
var (
60+
e2es *services.E2EServices
61+
62+
// TODO(random-liu): Change the following modes to sub-command.
63+
runServicesMode = flag.Bool("run-services-mode", false, "If true, only run services (etcd, apiserver) in current process, and not run test.")
64+
runKubeletMode = flag.Bool("run-kubelet-mode", false, "If true, only start kubelet, and not run test.")
65+
systemValidateMode = flag.Bool("system-validate-mode", false, "If true, only run system validation in current process, and not run test.")
66+
systemSpecFile = flag.String("system-spec-file", "", "The name of the system spec file that will be used for node conformance test. If it's unspecified or empty, the default system spec (system.DefaultSysSpec) will be used.")
67+
)
6668

6769
// registerNodeFlags registers flags specific to the node e2e test suite.
6870
func registerNodeFlags(flags *flag.FlagSet) {
6971
// Mark the test as node e2e when node flags are api.Registry.
7072
framework.TestContext.NodeE2E = true
73+
flags.StringVar(&framework.TestContext.BearerToken, "bearer-token", "", "The bearer token to authenticate with. If not specified, it would be a random token. Currently this token is only used in node e2e tests.")
7174
flags.StringVar(&framework.TestContext.NodeName, "node-name", "", "Name of the node to run tests on.")
7275
// TODO(random-liu): Move kubelet start logic out of the test.
7376
// TODO(random-liu): Move log fetch logic out of the test.
@@ -205,8 +208,12 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte {
205208
// Reference common test to make the import valid.
206209
commontest.CurrentSuite = commontest.NodeE2E
207210

208-
return nil
209-
}, func([]byte) {
211+
// ginkgo would spawn multiple processes to run tests.
212+
// Since the bearer token is generated randomly at run time,
213+
// we need to distribute the bearer token to other processes to make them use the same token.
214+
return []byte(framework.TestContext.BearerToken)
215+
}, func(token []byte) {
216+
framework.TestContext.BearerToken = string(token)
210217
// update test context with node configuration.
211218
gomega.Expect(updateTestContext()).To(gomega.Succeed(), "update test context with node config.")
212219
})

test/e2e_node/services/apiserver.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,17 @@ package services
1818

1919
import (
2020
"fmt"
21+
"io/ioutil"
2122
"net"
2223

2324
"k8s.io/apiserver/pkg/storage/storagebackend"
25+
2426
apiserver "k8s.io/kubernetes/cmd/kube-apiserver/app"
2527
"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
28+
"k8s.io/kubernetes/test/e2e/framework"
2629
)
2730

28-
const (
29-
clusterIPRange = "10.0.0.1/24"
30-
apiserverClientURL = "http://localhost:8080"
31-
apiserverHealthCheckURL = apiserverClientURL + "/healthz"
32-
)
31+
const clusterIPRange = "10.0.0.1/24"
3332

3433
// APIServer is a server which manages apiserver.
3534
type APIServer struct {
@@ -47,14 +46,23 @@ func NewAPIServer(storageConfig storagebackend.Config) *APIServer {
4746

4847
// Start starts the apiserver, returns when apiserver is ready.
4948
func (a *APIServer) Start() error {
49+
const tokenFilePath = "known_tokens.csv"
50+
5051
o := options.NewServerRunOptions()
5152
o.Etcd.StorageConfig = a.storageConfig
5253
_, ipnet, err := net.ParseCIDR(clusterIPRange)
5354
if err != nil {
5455
return err
5556
}
57+
o.SecureServing.BindAddress = net.ParseIP("127.0.0.1")
58+
// Disable insecure serving
59+
o.InsecureServing.BindPort = 0
5660
o.ServiceClusterIPRanges = ipnet.String()
5761
o.AllowPrivileged = true
62+
if err := generateTokenFile(tokenFilePath); err != nil {
63+
return fmt.Errorf("failed to generate token file %s: %v", tokenFilePath, err)
64+
}
65+
o.Authentication.TokenFile.TokenFile = tokenFilePath
5866
o.Admission.GenericAdmission.DisablePlugins = []string{"ServiceAccount", "TaintNodesByCondition"}
5967
errCh := make(chan error)
6068
go func() {
@@ -71,7 +79,7 @@ func (a *APIServer) Start() error {
7179
}
7280
}()
7381

74-
err = readinessCheck("apiserver", []string{apiserverHealthCheckURL}, errCh)
82+
err = readinessCheck("apiserver", []string{getAPIServerHealthCheckURL()}, errCh)
7583
if err != nil {
7684
return err
7785
}
@@ -96,9 +104,14 @@ func (a *APIServer) Name() string {
96104
}
97105

98106
func getAPIServerClientURL() string {
99-
return apiserverClientURL
107+
return framework.TestContext.Host
100108
}
101109

102110
func getAPIServerHealthCheckURL() string {
103-
return apiserverHealthCheckURL
111+
return framework.TestContext.Host + "/healthz"
112+
}
113+
114+
func generateTokenFile(tokenFilePath string) error {
115+
tokenFile := fmt.Sprintf("%s,kubelet,uid,system:masters\n", framework.TestContext.BearerToken)
116+
return ioutil.WriteFile(tokenFilePath, []byte(tokenFile), 0644)
104117
}

test/e2e_node/services/kubelet.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ import (
2727
"time"
2828

2929
"github.com/spf13/pflag"
30-
"k8s.io/klog/v2"
31-
3230
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3331
utilfeature "k8s.io/apiserver/pkg/util/feature"
3432
cliflag "k8s.io/component-base/cli/flag"
33+
"k8s.io/klog/v2"
3534
kubeletconfigv1beta1 "k8s.io/kubelet/config/v1beta1"
35+
3636
"k8s.io/kubernetes/cmd/kubelet/app/options"
3737
"k8s.io/kubernetes/pkg/features"
3838
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
@@ -356,21 +356,23 @@ func createPodDirectory() (string, error) {
356356

357357
// createKubeconfig creates a kubeconfig file at the fully qualified `path`. The parent dirs must exist.
358358
func createKubeconfig(path string) error {
359-
kubeconfig := []byte(`apiVersion: v1
359+
kubeconfig := []byte(fmt.Sprintf(`apiVersion: v1
360360
kind: Config
361361
users:
362362
- name: kubelet
363+
user:
364+
token: %s
363365
clusters:
364366
- cluster:
365-
server: ` + getAPIServerClientURL() + `
367+
server: %s
366368
insecure-skip-tls-verify: true
367369
name: local
368370
contexts:
369371
- context:
370372
cluster: local
371373
user: kubelet
372374
name: local-context
373-
current-context: local-context`)
375+
current-context: local-context`, framework.TestContext.BearerToken, getAPIServerClientURL()))
374376

375377
if err := ioutil.WriteFile(path, kubeconfig, 0666); err != nil {
376378
return err

test/e2e_node/services/namespace_controller.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ package services
1919
import (
2020
"time"
2121

22-
"k8s.io/api/core/v1"
22+
v1 "k8s.io/api/core/v1"
2323
"k8s.io/client-go/informers"
2424
clientset "k8s.io/client-go/kubernetes"
2525
"k8s.io/client-go/metadata"
2626
restclient "k8s.io/client-go/rest"
2727
namespacecontroller "k8s.io/kubernetes/pkg/controller/namespace"
28+
"k8s.io/kubernetes/test/e2e/framework"
2829
)
2930

3031
const (
@@ -49,7 +50,13 @@ func NewNamespaceController(host string) *NamespaceController {
4950

5051
// Start starts the namespace controller.
5152
func (n *NamespaceController) Start() error {
52-
config := restclient.AddUserAgent(&restclient.Config{Host: n.host}, ncName)
53+
config := restclient.AddUserAgent(&restclient.Config{
54+
Host: n.host,
55+
BearerToken: framework.TestContext.BearerToken,
56+
TLSClientConfig: restclient.TLSClientConfig{
57+
Insecure: true,
58+
},
59+
}, ncName)
5360

5461
// the namespace cleanup controller is very chatty. It makes lots of discovery calls and then it makes lots of delete calls.
5562
config.QPS = 50

test/e2e_node/services/services.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ import (
2424
"path"
2525
"testing"
2626

27+
utilfeature "k8s.io/apiserver/pkg/util/feature"
2728
"k8s.io/klog/v2"
2829

29-
utilfeature "k8s.io/apiserver/pkg/util/feature"
3030
"k8s.io/kubernetes/test/e2e/framework"
3131
)
3232

@@ -65,14 +65,16 @@ func NewE2EServices(monitorParent bool) *E2EServices {
6565
func (e *E2EServices) Start() error {
6666
var err error
6767
if !framework.TestContext.NodeConformance {
68+
if e.services, err = e.startInternalServices(); err != nil {
69+
return fmt.Errorf("failed to start internal services: %v", err)
70+
}
6871
// Start kubelet
6972
e.kubelet, err = e.startKubelet()
7073
if err != nil {
7174
return fmt.Errorf("failed to start kubelet: %v", err)
7275
}
7376
}
74-
e.services, err = e.startInternalServices()
75-
return err
77+
return nil
7678
}
7779

7880
// Stop stops the e2e services.
@@ -129,7 +131,11 @@ func (e *E2EServices) startInternalServices() (*server, error) {
129131
return nil, fmt.Errorf("can't get current binary: %v", err)
130132
}
131133
// Pass all flags into the child process, so that it will see the same flag set.
132-
startCmd := exec.Command(testBin, append([]string{"--run-services-mode"}, os.Args[1:]...)...)
134+
startCmd := exec.Command(testBin,
135+
append(
136+
[]string{"--run-services-mode", fmt.Sprintf("--bearer-token=%s", framework.TestContext.BearerToken)},
137+
os.Args[1:]...,
138+
)...)
133139
server := newServer("services", startCmd, nil, nil, getServicesHealthCheckURLs(), servicesLogFile, e.monitorParent, false)
134140
return server, server.start()
135141
}

0 commit comments

Comments
 (0)