Adds password protection for VNC on VMWare
This commit is contained in:
parent
9489c83f0f
commit
f961ce701b
|
@ -30,7 +30,7 @@ type VNCAddressFinder interface {
|
|||
VNCAddress(string, uint, uint) (string, uint, error)
|
||||
|
||||
// UpdateVMX, sets driver specific VNC values to VMX data.
|
||||
UpdateVMX(vncAddress string, vncPort uint, vmxData map[string]string)
|
||||
UpdateVMX(vncAddress, vncPassword string, vncPort uint, vmxData map[string]string)
|
||||
}
|
||||
|
||||
func (StepConfigureVNC) VNCAddress(vncBindAddress string, portMin, portMax uint) (string, uint, error) {
|
||||
|
@ -56,6 +56,21 @@ func (StepConfigureVNC) VNCAddress(vncBindAddress string, portMin, portMax uint)
|
|||
return vncBindAddress, vncPort, nil
|
||||
}
|
||||
|
||||
func VNCPassword() string {
|
||||
length := int(8)
|
||||
|
||||
charSet := []byte("1234567890-=qwertyuiop[]asdfghjkl;zxcvbnm,./!@#%^*()_+QWERTYUIOP{}|ASDFGHJKL:XCVBNM<>?")
|
||||
charSetLength := len(charSet)
|
||||
|
||||
password := make([]byte, length)
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
password[i] = charSet[rand.Intn(charSetLength)]
|
||||
}
|
||||
|
||||
return string(password)
|
||||
}
|
||||
|
||||
func (s *StepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction {
|
||||
driver := state.Get("driver").(Driver)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
@ -91,10 +106,12 @@ func (s *StepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction {
|
|||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
vncPassword := VNCPassword()
|
||||
|
||||
log.Printf("Found available VNC port: %d", vncPort)
|
||||
|
||||
vmxData := ParseVMX(string(vmxBytes))
|
||||
vncFinder.UpdateVMX(vncBindAddress, vncPort, vmxData)
|
||||
vncFinder.UpdateVMX(vncBindAddress, vncPassword, vncPort, vmxData)
|
||||
|
||||
if err := WriteVMX(vmxPath, vmxData); err != nil {
|
||||
err := fmt.Errorf("Error writing VMX data: %s", err)
|
||||
|
@ -105,14 +122,16 @@ func (s *StepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction {
|
|||
|
||||
state.Put("vnc_port", vncPort)
|
||||
state.Put("vnc_ip", vncBindAddress)
|
||||
state.Put("vnc_password", vncPassword)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (StepConfigureVNC) UpdateVMX(address string, port uint, data map[string]string) {
|
||||
func (StepConfigureVNC) UpdateVMX(address, password string, port uint, data map[string]string) {
|
||||
data["remotedisplay.vnc.enabled"] = "TRUE"
|
||||
data["remotedisplay.vnc.port"] = fmt.Sprintf("%d", port)
|
||||
data["remotedisplay.vnc.ip"] = address
|
||||
data["remotedisplay.vnc.password"] = password
|
||||
}
|
||||
|
||||
func (StepConfigureVNC) Cleanup(multistep.StateBag) {
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
diff a/builder/vmware/common/step_configure_vnc.go b/builder/vmware/common/step_configure_vnc.go (rejected hunks)
|
||||
@@ -52,6 +52,21 @@ func (StepConfigureVNC) VNCAddress(portMin, portMax uint) (string, uint, error)
|
||||
return "127.0.0.1", vncPort, nil
|
||||
}
|
||||
|
||||
+func VNCPassword() (string) {
|
||||
+ length := int(8)
|
||||
+
|
||||
+ charSet := []byte("1234567890-=qwertyuiop[]asdfghjkl;zxcvbnm,./!@#%^*()_+QWERTYUIOP{}|ASDFGHJKL:XCVBNM<>?")
|
||||
+ charSetLength := len(charSet)
|
||||
+
|
||||
+ password := make([]byte, length)
|
||||
+
|
||||
+ for i := 0; i < length; i++ {
|
||||
+ password[i] = charSet[ rand.Intn(charSetLength) ]
|
||||
+ }
|
||||
+
|
||||
+ return string(password)
|
||||
+}
|
||||
+
|
||||
func (s *StepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction {
|
||||
driver := state.Get("driver").(Driver)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
@@ -86,12 +101,14 @@ func (s *StepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction {
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
+ vncPassword := VNCPassword()
|
||||
|
||||
log.Printf("Found available VNC port: %d", vncPort)
|
||||
|
||||
vmxData := ParseVMX(string(vmxBytes))
|
||||
vmxData["remotedisplay.vnc.enabled"] = "TRUE"
|
||||
vmxData["remotedisplay.vnc.port"] = fmt.Sprintf("%d", vncPort)
|
||||
+ vmxData["remotedisplay.vnc.password"] = vncPassword
|
||||
|
||||
if err := WriteVMX(vmxPath, vmxData); err != nil {
|
||||
err := fmt.Errorf("Error writing VMX data: %s", err)
|
||||
@@ -102,6 +119,7 @@ func (s *StepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction {
|
||||
|
||||
state.Put("vnc_port", vncPort)
|
||||
state.Put("vnc_ip", vncIp)
|
||||
+ state.Put("vnc_password", vncPassword)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
|
@ -12,7 +12,7 @@ func TestStepConfigureVNC_implVNCAddressFinder(t *testing.T) {
|
|||
func TestStepConfigureVNC_UpdateVMX(t *testing.T) {
|
||||
var s StepConfigureVNC
|
||||
data := make(map[string]string)
|
||||
s.UpdateVMX("0.0.0.0", 5900, data)
|
||||
s.UpdateVMX("0.0.0.0", "", 5900, data)
|
||||
if ip := data["remotedisplay.vnc.ip"]; ip != "0.0.0.0" {
|
||||
t.Errorf("bad VMX data for key remotedisplay.vnc.ip: %v", ip)
|
||||
}
|
||||
|
|
|
@ -38,15 +38,17 @@ func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction {
|
|||
if s.Headless {
|
||||
vncIpRaw, vncIpOk := state.GetOk("vnc_ip")
|
||||
vncPortRaw, vncPortOk := state.GetOk("vnc_port")
|
||||
vncPasswordRaw, vncPasswordOk := state.GetOk("vnc_password")
|
||||
|
||||
if vncIpOk && vncPortOk {
|
||||
if vncIpOk && vncPortOk && vncPasswordOk {
|
||||
vncIp := vncIpRaw.(string)
|
||||
vncPort := vncPortRaw.(uint)
|
||||
vncPassword := vncPasswordRaw.(string)
|
||||
|
||||
ui.Message(fmt.Sprintf(
|
||||
"The VM will be run headless, without a GUI. If you want to\n"+
|
||||
"view the screen of the VM, connect via VNC without a password to\n"+
|
||||
"%s:%d", vncIp, vncPort))
|
||||
"view the screen of the VM, connect via VNC with the password %s to\n"+
|
||||
"%s:%d", vncPassword, vncIp, vncPort))
|
||||
} else {
|
||||
ui.Message("The VM will be run headless, without a GUI, as configured.\n" +
|
||||
"If the run isn't succeeding as you expect, please enable the GUI\n" +
|
||||
|
|
|
@ -46,6 +46,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction
|
|||
ui := state.Get("ui").(packer.Ui)
|
||||
vncIp := state.Get("vnc_ip").(string)
|
||||
vncPort := state.Get("vnc_port").(uint)
|
||||
vncPassword := state.Get("vnc_password")
|
||||
|
||||
var pauseFn multistep.DebugPauseFn
|
||||
if debug {
|
||||
|
@ -63,7 +64,15 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction
|
|||
}
|
||||
defer nc.Close()
|
||||
|
||||
c, err := vnc.Client(nc, &vnc.ClientConfig{Exclusive: false})
|
||||
var auth []vnc.ClientAuth
|
||||
|
||||
if vncPassword != nil {
|
||||
auth = []vnc.ClientAuth{&vnc.PasswordAuth{Password: vncPassword.(string)}}
|
||||
} else {
|
||||
auth = []vnc.ClientAuth{}
|
||||
}
|
||||
|
||||
c, err := vnc.Client(nc, &vnc.ClientConfig{Auth: auth, Exclusive: true})
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error handshaking with VNC: %s", err)
|
||||
state.Put("error", err)
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
diff a/builder/vmware/common/step_type_boot_command.go b/builder/vmware/common/step_type_boot_command.go (rejected hunks)
|
||||
@@ -45,6 +45,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vncIp := state.Get("vnc_ip").(string)
|
||||
vncPort := state.Get("vnc_port").(uint)
|
||||
+ vncPassword := state.Get("vnc_password")
|
||||
|
||||
// Connect to VNC
|
||||
ui.Say("Connecting to VM via VNC")
|
||||
@@ -57,7 +58,15 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
- c, err := vnc.Client(nc, &vnc.ClientConfig{Exclusive: true})
|
||||
+ var auth []vnc.ClientAuth
|
||||
+
|
||||
+ if vncPassword != nil {
|
||||
+ auth = []vnc.ClientAuth{&vnc.PasswordAuth{Password: vncPassword.(string)}}
|
||||
+ } else {
|
||||
+ auth = []vnc.ClientAuth{}
|
||||
+ }
|
||||
+
|
||||
+ c, err := vnc.Client(nc, &vnc.ClientConfig{Auth: auth, Exclusive: true})
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error handshaking with VNC: %s", err)
|
||||
state.Put("error", err)
|
|
@ -231,10 +231,11 @@ func (d *ESX5Driver) VNCAddress(_ string, portMin, portMax uint) (string, uint,
|
|||
}
|
||||
|
||||
// UpdateVMX, adds the VNC port to the VMX data.
|
||||
func (ESX5Driver) UpdateVMX(_ string, port uint, data map[string]string) {
|
||||
func (ESX5Driver) UpdateVMX(_, password string, port uint, data map[string]string) {
|
||||
// Do not set remotedisplay.vnc.ip - this breaks ESXi.
|
||||
data["remotedisplay.vnc.enabled"] = "TRUE"
|
||||
data["remotedisplay.vnc.port"] = fmt.Sprintf("%d", port)
|
||||
data["remotedisplay.vnc.password"] = password
|
||||
}
|
||||
|
||||
func (d *ESX5Driver) CommHost(state multistep.StateBag) (string, error) {
|
||||
|
|
|
@ -13,6 +13,22 @@ func TestESX5Driver_implDriver(t *testing.T) {
|
|||
var _ vmwcommon.Driver = new(ESX5Driver)
|
||||
}
|
||||
|
||||
func TestESX5Driver_UpdateVMX(t *testing.T) {
|
||||
var driver ESX5Driver
|
||||
data := make(map[string]string)
|
||||
driver.UpdateVMX("0.0.0.0", "", 5900, data)
|
||||
if _, ok := data["remotedisplay.vnc.ip"]; ok {
|
||||
// Do not add the remotedisplay.vnc.ip on ESXi
|
||||
t.Fatal("invalid VMX data key: remotedisplay.vnc.ip")
|
||||
}
|
||||
if enabled := data["remotedisplay.vnc.enabled"]; enabled != "TRUE" {
|
||||
t.Errorf("bad VMX data for key remotedisplay.vnc.enabled: %v", enabled)
|
||||
}
|
||||
if port := data["remotedisplay.vnc.port"]; port != fmt.Sprint(port) {
|
||||
t.Errorf("bad VMX data for key remotedisplay.vnc.port: %v", port)
|
||||
}
|
||||
}
|
||||
|
||||
func TestESX5Driver_implOutputDir(t *testing.T) {
|
||||
var _ vmwcommon.OutputDir = new(ESX5Driver)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue