Merge pull request #17748 from reancloud/winrm-ntlm
Support NTLM for WinRM communicators.
This commit is contained in:
commit
060a3bc6d2
|
@ -62,6 +62,9 @@ func (c *Communicator) Connect(o terraform.UIOutput) error {
|
||||||
|
|
||||||
params := winrm.DefaultParameters
|
params := winrm.DefaultParameters
|
||||||
params.Timeout = formatDuration(c.Timeout())
|
params.Timeout = formatDuration(c.Timeout())
|
||||||
|
if c.connInfo.NTLM == true {
|
||||||
|
params.TransportDecorator = func() winrm.Transporter { return &winrm.ClientNTLM{} }
|
||||||
|
}
|
||||||
|
|
||||||
client, err := winrm.NewClientWithParameters(
|
client, err := winrm.NewClientWithParameters(
|
||||||
c.endpoint, c.connInfo.User, c.connInfo.Password, params)
|
c.endpoint, c.connInfo.User, c.connInfo.Password, params)
|
||||||
|
@ -78,6 +81,7 @@ func (c *Communicator) Connect(o terraform.UIOutput) error {
|
||||||
" Password: %t\n"+
|
" Password: %t\n"+
|
||||||
" HTTPS: %t\n"+
|
" HTTPS: %t\n"+
|
||||||
" Insecure: %t\n"+
|
" Insecure: %t\n"+
|
||||||
|
" NTLM: %t\n"+
|
||||||
" CACert: %t",
|
" CACert: %t",
|
||||||
c.connInfo.Host,
|
c.connInfo.Host,
|
||||||
c.connInfo.Port,
|
c.connInfo.Port,
|
||||||
|
@ -85,6 +89,7 @@ func (c *Communicator) Connect(o terraform.UIOutput) error {
|
||||||
c.connInfo.Password != "",
|
c.connInfo.Password != "",
|
||||||
c.connInfo.HTTPS,
|
c.connInfo.HTTPS,
|
||||||
c.connInfo.Insecure,
|
c.connInfo.Insecure,
|
||||||
|
c.connInfo.NTLM,
|
||||||
c.connInfo.CACert != "",
|
c.connInfo.CACert != "",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -213,6 +218,10 @@ func (c *Communicator) newCopyClient() (*winrmcp.Winrmcp, error) {
|
||||||
MaxOperationsPerShell: 15, // lowest common denominator
|
MaxOperationsPerShell: 15, // lowest common denominator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.connInfo.NTLM == true {
|
||||||
|
config.TransportDecorator = func() winrm.Transporter { return &winrm.ClientNTLM{} }
|
||||||
|
}
|
||||||
|
|
||||||
if c.connInfo.CACert != "" {
|
if c.connInfo.CACert != "" {
|
||||||
config.CACertBytes = []byte(c.connInfo.CACert)
|
config.CACertBytes = []byte(c.connInfo.CACert)
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,6 +155,73 @@ func TestScriptPath(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNoTransportDecorator(t *testing.T) {
|
||||||
|
wrm := newMockWinRMServer(t)
|
||||||
|
defer wrm.Close()
|
||||||
|
|
||||||
|
r := &terraform.InstanceState{
|
||||||
|
Ephemeral: terraform.EphemeralState{
|
||||||
|
ConnInfo: map[string]string{
|
||||||
|
"type": "winrm",
|
||||||
|
"user": "user",
|
||||||
|
"password": "pass",
|
||||||
|
"host": wrm.Host,
|
||||||
|
"port": strconv.Itoa(wrm.Port),
|
||||||
|
"timeout": "30s",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := New(r)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error creating communicator: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.Connect(nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error connecting communicator: %s", err)
|
||||||
|
}
|
||||||
|
defer c.Disconnect()
|
||||||
|
|
||||||
|
if c.client.TransportDecorator != nil {
|
||||||
|
t.Fatal("bad TransportDecorator: expected nil, got non-nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTransportDecorator(t *testing.T) {
|
||||||
|
wrm := newMockWinRMServer(t)
|
||||||
|
defer wrm.Close()
|
||||||
|
|
||||||
|
r := &terraform.InstanceState{
|
||||||
|
Ephemeral: terraform.EphemeralState{
|
||||||
|
ConnInfo: map[string]string{
|
||||||
|
"type": "winrm",
|
||||||
|
"user": "user",
|
||||||
|
"password": "pass",
|
||||||
|
"host": wrm.Host,
|
||||||
|
"port": strconv.Itoa(wrm.Port),
|
||||||
|
"use_ntlm": "true",
|
||||||
|
"timeout": "30s",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := New(r)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error creating communicator: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.Connect(nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error connecting communicator: %s", err)
|
||||||
|
}
|
||||||
|
defer c.Disconnect()
|
||||||
|
|
||||||
|
if c.client.TransportDecorator == nil {
|
||||||
|
t.Fatal("bad TransportDecorator: expected non-nil, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestScriptPath_randSeed(t *testing.T) {
|
func TestScriptPath_randSeed(t *testing.T) {
|
||||||
// Pre GH-4186 fix, this value was the deterministic start the pseudorandom
|
// Pre GH-4186 fix, this value was the deterministic start the pseudorandom
|
||||||
// chain of unseeded math/rand values for Int31().
|
// chain of unseeded math/rand values for Int31().
|
||||||
|
|
|
@ -37,6 +37,7 @@ type connectionInfo struct {
|
||||||
Port int
|
Port int
|
||||||
HTTPS bool
|
HTTPS bool
|
||||||
Insecure bool
|
Insecure bool
|
||||||
|
NTLM bool `mapstructure:"use_ntlm"`
|
||||||
CACert string `mapstructure:"cacert"`
|
CACert string `mapstructure:"cacert"`
|
||||||
Timeout string
|
Timeout string
|
||||||
ScriptPath string `mapstructure:"script_path"`
|
ScriptPath string `mapstructure:"script_path"`
|
||||||
|
|
|
@ -16,6 +16,7 @@ func TestProvisioner_connInfo(t *testing.T) {
|
||||||
"host": "127.0.0.1",
|
"host": "127.0.0.1",
|
||||||
"port": "5985",
|
"port": "5985",
|
||||||
"https": "true",
|
"https": "true",
|
||||||
|
"use_ntlm": "true",
|
||||||
"timeout": "30s",
|
"timeout": "30s",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -41,6 +42,9 @@ func TestProvisioner_connInfo(t *testing.T) {
|
||||||
if conf.HTTPS != true {
|
if conf.HTTPS != true {
|
||||||
t.Fatalf("expected: %v: got: %v", true, conf)
|
t.Fatalf("expected: %v: got: %v", true, conf)
|
||||||
}
|
}
|
||||||
|
if conf.NTLM != true {
|
||||||
|
t.Fatalf("expected: %v: got: %v", true, conf)
|
||||||
|
}
|
||||||
if conf.Timeout != "30s" {
|
if conf.Timeout != "30s" {
|
||||||
t.Fatalf("expected: %v: got: %v", "30s", conf)
|
t.Fatalf("expected: %v: got: %v", "30s", conf)
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,6 +157,7 @@ func (n *EvalValidateProvisioner) validateConnConfig(connConfig *ResourceConfig)
|
||||||
// For type=winrm only (enforced in winrm communicator)
|
// For type=winrm only (enforced in winrm communicator)
|
||||||
HTTPS interface{} `mapstructure:"https"`
|
HTTPS interface{} `mapstructure:"https"`
|
||||||
Insecure interface{} `mapstructure:"insecure"`
|
Insecure interface{} `mapstructure:"insecure"`
|
||||||
|
NTLM interface{} `mapstructure:"use_ntlm"`
|
||||||
CACert interface{} `mapstructure:"cacert"`
|
CACert interface{} `mapstructure:"cacert"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,8 @@ provisioner "file" {
|
||||||
|
|
||||||
* `insecure` - Set to `true` to not validate the HTTPS certificate chain.
|
* `insecure` - Set to `true` to not validate the HTTPS certificate chain.
|
||||||
|
|
||||||
|
* `use_ntlm` - Set to `true` to use NTLM authentication, rather than default (basic authentication), removing the requirement for basic authentication to be enabled within the target guest. Further reading for remote connection authentication can be found [here](https://msdn.microsoft.com/en-us/library/aa384295(v=vs.85).aspx).
|
||||||
|
|
||||||
* `cacert` - The CA certificate to validate against.
|
* `cacert` - The CA certificate to validate against.
|
||||||
|
|
||||||
<a id="bastion"></a>
|
<a id="bastion"></a>
|
||||||
|
|
Loading…
Reference in New Issue