package winrm
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"strings"
"github.com/masterzen/winrm/soap"
"github.com/jcmturner/gokrb5/v8/client"
"github.com/jcmturner/gokrb5/v8/config"
"github.com/jcmturner/gokrb5/v8/credentials"
"github.com/jcmturner/gokrb5/v8/spnego"
)
type Settings struct {
WinRMUsername string
WinRMPassword string
WinRMHost string
WinRMPort int
WinRMProto string
WinRMInsecure bool
KrbRealm string
KrbConfig string
KrbSpn string
KrbCCache string
WinRMUseNTLM bool
WinRMPassCredentials bool
}
type ClientKerberos struct {
clientRequest
Username string
Password string
Realm string
Hostname string
Port int
Proto string
SPN string
KrbConf string
KrbCCache string
}
func NewClientKerberos (settings *Settings ) *ClientKerberos {
return &ClientKerberos {
Username : settings .WinRMUsername ,
Password : settings .WinRMPassword ,
Realm : settings .KrbRealm ,
Hostname : settings .WinRMHost ,
Port : settings .WinRMPort ,
Proto : settings .WinRMProto ,
KrbConf : settings .KrbConfig ,
KrbCCache : settings .KrbCCache ,
SPN : settings .KrbSpn ,
}
}
func (c *ClientKerberos ) Transport (endpoint *Endpoint ) error {
return c .clientRequest .Transport (endpoint )
}
func (c *ClientKerberos ) Post (clt *Client , request *soap .SoapMessage ) (string , error ) {
cfg , err := config .Load (c .KrbConf )
if err != nil {
return "" , err
}
var kerberosClient *client .Client
if len (c .KrbCCache ) > 0 {
b , err := ioutil .ReadFile (c .KrbCCache )
if err != nil {
return "" , fmt .Errorf ("unable to read ccache file %s: %w" , c .KrbCCache , err )
}
cc := new (credentials .CCache )
err = cc .Unmarshal (b )
if err != nil {
return "" , fmt .Errorf ("unable to parse ccache file %s: %w" , c .KrbCCache , err )
}
kerberosClient , err = client .NewFromCCache (cc , cfg , client .DisablePAFXFAST (true ))
if err != nil {
return "" , fmt .Errorf ("unable to create kerberos client from ccache: %w" , err )
}
} else {
kerberosClient = client .NewWithPassword (c .Username , c .Realm , c .Password , cfg ,
client .DisablePAFXFAST (true ), client .AssumePreAuthentication (true ))
}
winrmURL := fmt .Sprintf ("%s://%s:%d/wsman" , c .Proto , c .Hostname , c .Port )
winRMRequest , _ := http .NewRequest ("POST" , winrmURL , strings .NewReader (request .String ()))
winRMRequest .Header .Add ("Content-Type" , "application/soap+xml;charset=UTF-8" )
err = spnego .SetSPNEGOHeader (kerberosClient , winRMRequest , c .SPN )
if err != nil {
return "" , fmt .Errorf ("unable to set SPNego Header: %w" , err )
}
httpClient := &http .Client {Transport : c .transport }
resp , err := httpClient .Do (winRMRequest )
if err != nil {
return "" , err
}
defer resp .Body .Close ()
if resp .StatusCode != 200 {
var bodyMsg string
respBody , err := io .ReadAll (resp .Body )
if err != nil {
bodyMsg = fmt .Sprintf ("Error retrieving the response's body: %s" , err )
} else {
bodyMsg = fmt .Sprintf ("Response body:\n%s" , string (respBody ))
}
return "" , fmt .Errorf ("request returned: %d - %s. %s" , resp .StatusCode , resp .Status , bodyMsg )
}
body , err := ioutil .ReadAll (resp .Body )
if err != nil {
return "" , err
}
return string (body ), err
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .