Skip to content

Commit 5248f79

Browse files
author
seborama
committed
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 57a4ddc commit 5248f79

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
@@ -70,6 +70,8 @@ const (
7070
disableDriverMounts = "disable-driver-mounts"
7171
cacheImages = "cache-images"
7272
uuid = "uuid"
73+
vpnkitSock = "hyperkit-vpnkit-sock"
74+
vsockPorts = "hyperkit-vsock-ports"
7375
)
7476

7577
var (
@@ -135,6 +137,8 @@ func runStart(cmd *cobra.Command, args []string) {
135137
CPUs: viper.GetInt(cpus),
136138
DiskSize: diskSizeMB,
137139
VMDriver: viper.GetString(vmDriver),
140+
HyperkitVpnKitSock: viper.GetString(vpnkitSock),
141+
HyperkitVSockPorts: viper.GetStringSlice(vsockPorts),
138142
XhyveDiskDriver: viper.GetString(xhyveDiskDriver),
139143
NFSShare: viper.GetStringSlice(NFSShare),
140144
NFSSharesRoot: viper.GetString(NFSSharesRoot),
@@ -321,8 +325,7 @@ func runStart(cmd *cobra.Command, args []string) {
321325
if viper.GetBool(cfg.WantNoneDriverWarning) {
322326
fmt.Println(`===================
323327
WARNING: IT IS RECOMMENDED NOT TO RUN THE NONE DRIVER ON PERSONAL WORKSTATIONS
324-
The 'none' driver will run an insecure kubernetes apiserver as root that may leave the host vulnerable to CSRF attacks
325-
`)
328+
The 'none' driver will run an insecure kubernetes apiserver as root that may leave the host vulnerable to CSRF attacks` + "\n")
326329
}
327330

328331
if os.Getenv("CHANGE_MINIKUBE_NONE_USER") == "" {
@@ -399,6 +402,9 @@ func init() {
399402
`A set of key=value pairs that describe configuration that may be passed to different components.
400403
The key should be '.' separated, and the first part before the dot is the component to apply the configuration to.
401404
Valid components are: kubelet, apiserver, controller-manager, etcd, proxy, scheduler.`)
405+
startCmd.Flags().String(uuid, "", "Provide VM UUID to restore MAC address (only supported with Hyperkit driver).")
406+
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.")
407+
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).")
402408
viper.BindPFlags(startCmd.Flags())
403409
RootCmd.AddCommand(startCmd)
404410
}

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)