Skip to content

Commit ee73cbd

Browse files
seboramadlorenc
seborama
authored andcommitted
Added hyperkit options for enterprise VPN support
The purpose of these changes is to enhance Hyperkit support from the minikube command line for better integration with enterprise networks behind a VPN. uuid: Provide VM UUID to restore MAC address (only supported with Hyperkit driver). vpnkitSock: Location of the VPNKit socket used for networking. If empty, disables Hyperkit VPNKitSock, if 'auto' uses Docker for Mac VPNKit connection, otherwise uses the specified VSock." vsockPorts: List of guest VSock ports that should be exposed as sockets on the host (Only supported on with hyperkit now). Note: tests pass but file: `vendor/github.com/google/certificate-transparency/go/x509/root_darwin.go` has to be edited to correct an issue - not committed since this is in the vendor directory.
1 parent 5ed8a7e commit ee73cbd

File tree

5 files changed

+144
-8
lines changed

5 files changed

+144
-8
lines changed

cmd/minikube/cmd/start.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ const (
7171
disableDriverMounts = "disable-driver-mounts"
7272
cacheImages = "cache-images"
7373
uuid = "uuid"
74+
vpnkitSock = "hyperkit-vpnkit-sock"
75+
vsockPorts = "hyperkit-vsock-ports"
7476
)
7577

7678
var (
@@ -140,6 +142,8 @@ func runStart(cmd *cobra.Command, args []string) {
140142
CPUs: viper.GetInt(cpus),
141143
DiskSize: diskSizeMB,
142144
VMDriver: viper.GetString(vmDriver),
145+
HyperkitVpnKitSock: viper.GetString(vpnkitSock),
146+
HyperkitVSockPorts: viper.GetStringSlice(vsockPorts),
143147
XhyveDiskDriver: viper.GetString(xhyveDiskDriver),
144148
NFSShare: viper.GetStringSlice(NFSShare),
145149
NFSSharesRoot: viper.GetString(NFSSharesRoot),
@@ -334,8 +338,7 @@ func runStart(cmd *cobra.Command, args []string) {
334338
if viper.GetBool(cfg.WantNoneDriverWarning) {
335339
fmt.Println(`===================
336340
WARNING: IT IS RECOMMENDED NOT TO RUN THE NONE DRIVER ON PERSONAL WORKSTATIONS
337-
The 'none' driver will run an insecure kubernetes apiserver as root that may leave the host vulnerable to CSRF attacks
338-
`)
341+
The 'none' driver will run an insecure kubernetes apiserver as root that may leave the host vulnerable to CSRF attacks` + "\n")
339342
}
340343

341344
if os.Getenv("CHANGE_MINIKUBE_NONE_USER") == "" {
@@ -412,6 +415,9 @@ func init() {
412415
`A set of key=value pairs that describe configuration that may be passed to different components.
413416
The key should be '.' separated, and the first part before the dot is the component to apply the configuration to.
414417
Valid components are: kubelet, apiserver, controller-manager, etcd, proxy, scheduler.`)
418+
startCmd.Flags().String(uuid, "", "Provide VM UUID to restore MAC address (only supported with Hyperkit driver).")
419+
startCmd.Flags().String(vpnkitSock, "", "Location of the VPNKit socket used for networking. If empty, disables Hyperkit VPNKitSock, if 'auto' uses Docker for Mac VPNKit connection, otherwise uses the specified VSock.")
420+
startCmd.Flags().StringSlice(vsockPorts, []string{}, "List of guest VSock ports that should be exposed as sockets on the host (Only supported on with hyperkit now).")
415421
viper.BindPFlags(startCmd.Flags())
416422
RootCmd.AddCommand(startCmd)
417423
}

pkg/drivers/hyperkit/driver.go

+40-5
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"os/user"
2626
"path"
2727
"path/filepath"
28+
"strconv"
2829
"strings"
2930
"syscall"
3031
"time"
@@ -59,6 +60,8 @@ type Driver struct {
5960
NFSShares []string
6061
NFSSharesRoot string
6162
UUID string
63+
VpnKitSock string
64+
VSockPorts []string
6265
}
6366

6467
func NewDriver(hostName, storePath string) *Driver {
@@ -92,7 +95,7 @@ func (d *Driver) Create() error {
9295

9396
isoPath := d.ResolveStorePath(isoFilename)
9497
if err := d.extractKernel(isoPath); err != nil {
95-
return err
98+
return errors.Wrap(err, "extracting kernel")
9699
}
97100

98101
return d.Start()
@@ -164,9 +167,9 @@ func (d *Driver) Restart() error {
164167

165168
// Start a host
166169
func (d *Driver) Start() error {
167-
h, err := hyperkit.New("", "", filepath.Join(d.StorePath, "machines", d.MachineName))
170+
h, err := hyperkit.New("", d.VpnKitSock, filepath.Join(d.StorePath, "machines", d.MachineName))
168171
if err != nil {
169-
return err
172+
return errors.Wrap(err, "new-ing Hyperkit")
170173
}
171174

172175
// TODO: handle the rest of our settings.
@@ -179,10 +182,17 @@ func (d *Driver) Start() error {
179182
h.Memory = d.Memory
180183
h.UUID = d.UUID
181184

185+
if vsockPorts, err := d.extractVSockPorts(); err != nil {
186+
return err
187+
} else if len(vsockPorts) >= 1 {
188+
h.VSock = true
189+
h.VSockPorts = vsockPorts
190+
}
191+
182192
log.Infof("Using UUID %s", h.UUID)
183193
mac, err := GetMACAddressFromUUID(h.UUID)
184194
if err != nil {
185-
return err
195+
return errors.Wrap(err, "getting MAC address from UUID")
186196
}
187197

188198
// Need to strip 0's
@@ -197,7 +207,7 @@ func (d *Driver) Start() error {
197207
}
198208
log.Infof("Starting with cmdline: %s", d.Cmdline)
199209
if err := h.Start(d.Cmdline); err != nil {
200-
return err
210+
return errors.Wrapf(err, "starting with cmd line: %s", d.Cmdline)
201211
}
202212

203213
getIP := func() error {
@@ -250,6 +260,31 @@ func (d *Driver) extractKernel(isoPath string) error {
250260
return nil
251261
}
252262

263+
// InvalidPortNumberError implements the Error interface.
264+
// It is used when a VSockPorts port number cannot be recognised as an integer.
265+
type InvalidPortNumberError string
266+
267+
// Error returns an Error for InvalidPortNumberError
268+
func (port InvalidPortNumberError) Error() string {
269+
return fmt.Sprintf("vsock port '%s' is not an integer", string(port))
270+
}
271+
272+
func (d *Driver) extractVSockPorts() ([]int, error) {
273+
vsockPorts := make([]int, 0, len(d.VSockPorts))
274+
275+
for _, port := range d.VSockPorts {
276+
p, err := strconv.Atoi(port)
277+
if err != nil {
278+
var err InvalidPortNumberError
279+
err = InvalidPortNumberError(port)
280+
return nil, err
281+
}
282+
vsockPorts = append(vsockPorts, p)
283+
}
284+
285+
return vsockPorts, nil
286+
}
287+
253288
func (d *Driver) setupNFSShare() error {
254289
user, err := user.Current()
255290
if err != nil {

pkg/drivers/hyperkit/driver_test.go

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// +build darwin
2+
3+
/*
4+
Copyright 2018 The Kubernetes Authors All rights reserved.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
package hyperkit
20+
21+
import (
22+
"testing"
23+
)
24+
25+
func Test_portExtraction(t *testing.T) {
26+
tests := []struct {
27+
name string
28+
ports []string
29+
want []int
30+
wantErr error
31+
}{
32+
{
33+
"valid_empty",
34+
[]string{},
35+
[]int{},
36+
nil,
37+
},
38+
{
39+
"valid_list",
40+
[]string{"10", "20", "30"},
41+
[]int{10, 20, 30},
42+
nil,
43+
},
44+
{
45+
"invalid",
46+
[]string{"8080", "not_an_integer"},
47+
nil,
48+
InvalidPortNumberError("not_an_integer"),
49+
},
50+
}
51+
52+
for _, tt := range tests {
53+
d := NewDriver("", "")
54+
d.VSockPorts = tt.ports
55+
got, gotErr := d.extractVSockPorts()
56+
if !testEq(got, tt.want) {
57+
t.Errorf("extractVSockPorts() got: %v, want: %v", got, tt.want)
58+
}
59+
if gotErr != tt.wantErr {
60+
t.Errorf("extractVSockPorts() gotErr: %s, wantErr: %s", gotErr.Error(), tt.wantErr.Error())
61+
}
62+
}
63+
}
64+
65+
func testEq(a, b []int) bool {
66+
67+
if a == nil && b == nil {
68+
return true
69+
}
70+
71+
if a == nil || b == nil {
72+
return false
73+
}
74+
75+
if len(a) != len(b) {
76+
return false
77+
}
78+
79+
for i := range a {
80+
if a[i] != b[i] {
81+
return false
82+
}
83+
}
84+
85+
return true
86+
}

pkg/minikube/config/types.go

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ type MachineConfig struct {
3535
CPUs int
3636
DiskSize int
3737
VMDriver string
38+
HyperkitVpnKitSock string // Only used by the Hyperkit driver
39+
HyperkitVSockPorts []string // Only used by the Hyperkit driver
3840
XhyveDiskDriver string // Only used by the xhyve driver
3941
DockerEnv []string // Each entry is formatted as KEY=VALUE.
4042
InsecureRegistry []string

pkg/minikube/drivers/hyperkit/driver.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ func init() {
3636
}
3737

3838
func createHyperkitHost(config cfg.MachineConfig) interface{} {
39+
uuID := config.UUID
40+
if uuID == "" {
41+
uuID = uuid.NewUUID().String()
42+
}
43+
3944
return &hyperkit.Driver{
4045
BaseDriver: &drivers.BaseDriver{
4146
MachineName: cfg.GetMachineName(),
@@ -48,7 +53,9 @@ func createHyperkitHost(config cfg.MachineConfig) interface{} {
4853
CPU: config.CPUs,
4954
NFSShares: config.NFSShare,
5055
NFSSharesRoot: config.NFSSharesRoot,
51-
UUID: uuid.NewUUID().String(),
56+
UUID: uuID,
57+
VpnKitSock: config.HyperkitVpnKitSock,
58+
VSockPorts: config.HyperkitVSockPorts,
5259
Cmdline: "loglevel=3 user=docker console=ttyS0 console=tty0 noembed nomodeset norestore waitusb=10 systemd.legacy_systemd_cgroup_controller=yes base host=" + cfg.GetMachineName(),
5360
}
5461
}

0 commit comments

Comments
 (0)