go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/powershell.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package resources 5 6 import ( 7 "bytes" 8 "io" 9 "sync" 10 11 "github.com/rs/zerolog/log" 12 "go.mondoo.com/cnquery/providers-sdk/v1/plugin" 13 "go.mondoo.com/cnquery/providers/os/connection/shared" 14 "go.mondoo.com/cnquery/providers/os/resources/powershell" 15 "golang.org/x/net/html/charset" 16 "golang.org/x/text/transform" 17 ) 18 19 type mqlPowershellInternal struct { 20 lock sync.Mutex 21 executed bool 22 executeErr error 23 } 24 25 // TODO: consider sharing more code with command resource 26 func (c *mqlPowershell) id() (string, error) { 27 return c.Script.Data, nil 28 } 29 30 func (c *mqlPowershell) execute() error { 31 c.lock.Lock() 32 defer c.lock.Unlock() 33 34 if c.executed { 35 return c.executeErr 36 } 37 c.executed = true 38 39 conn := c.MqlRuntime.Connection.(shared.Connection) 40 cmd := c.Script.Data 41 42 // encode the powershell command 43 encodedCmd := powershell.Encode(cmd) 44 x, err := conn.RunCommand(encodedCmd) 45 c.executeErr = err 46 if err != nil { 47 c.Exitcode = plugin.TValue[int64]{Error: err, State: plugin.StateIsSet} 48 c.Stdout = plugin.TValue[string]{Error: err, State: plugin.StateIsSet} 49 c.Stderr = plugin.TValue[string]{Error: err, State: plugin.StateIsSet} 50 return err 51 } 52 53 c.Exitcode = plugin.TValue[int64]{Data: int64(x.ExitStatus), State: plugin.StateIsSet} 54 55 stdout, err := io.ReadAll(x.Stdout) 56 if err != nil { 57 c.Stdout = plugin.TValue[string]{Error: err, State: plugin.StateIsSet} 58 } else { 59 out, err := convertToUtf8Encoding(stdout) 60 c.Stdout = plugin.TValue[string]{Data: out, Error: err, State: plugin.StateIsSet} 61 } 62 63 stderr, err := io.ReadAll(x.Stderr) 64 if err != nil { 65 c.Stdout = plugin.TValue[string]{Error: err, State: plugin.StateIsSet} 66 } else { 67 serr, err := convertToUtf8Encoding(stderr) 68 c.Stderr = plugin.TValue[string]{Data: string(serr), Error: err, State: plugin.StateIsSet} 69 } 70 71 return nil 72 } 73 74 func convertToUtf8Encoding(out []byte) (string, error) { 75 enc, name, _ := charset.DetermineEncoding(out, "") 76 log.Trace().Str("encoding", name).Msg("check powershell results charset") 77 r := transform.NewReader(bytes.NewReader(out), enc.NewDecoder()) 78 utf8out, err := io.ReadAll(r) 79 if err != nil { 80 return "", err 81 } 82 return string(utf8out), nil 83 } 84 85 func (c *mqlPowershell) stdout() (string, error) { 86 return "", c.execute() 87 } 88 89 func (c *mqlPowershell) stderr() (string, error) { 90 return "", c.execute() 91 } 92 93 func (c *mqlPowershell) exitcode() (int64, error) { 94 return 0, c.execute() 95 }