go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/connection/shared/shared.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package shared 5 6 import ( 7 "io" 8 "io/fs" 9 "os" 10 "regexp" 11 "strings" 12 "time" 13 14 "github.com/spf13/afero" 15 "go.mondoo.com/cnquery/llx" 16 "go.mondoo.com/cnquery/providers-sdk/v1/inventory" 17 ) 18 19 type ConnectionType string 20 21 type Connection interface { 22 RunCommand(command string) (*Command, error) 23 FileInfo(path string) (FileInfoDetails, error) 24 FileSystem() afero.Fs 25 ID() uint32 26 Name() string 27 Type() ConnectionType 28 Asset() *inventory.Asset 29 Capabilities() Capabilities 30 } 31 32 type SimpleConnection interface { 33 ID() uint32 34 Name() string 35 Type() ConnectionType 36 Asset() *inventory.Asset 37 } 38 39 type Command struct { 40 Command string 41 Stats PerfStats 42 Stdout io.ReadWriter 43 Stderr io.ReadWriter 44 ExitStatus int 45 } 46 47 type Capabilities byte 48 49 const ( 50 Capability_RunCommand Capabilities = 1 << iota 51 Capability_File 52 Capability_FindFile 53 Capability_FileSearch 54 ) 55 56 func (c Capabilities) Has(other Capabilities) bool { 57 return c&other == other 58 } 59 60 func (c Capabilities) String() []string { 61 res := []string{} 62 if c.Has(Capability_RunCommand) { 63 res = append(res, "run-command") 64 } 65 if c.Has(Capability_File) { 66 res = append(res, "file") 67 } 68 if c.Has(Capability_FindFile) { 69 res = append(res, "find-file") 70 } 71 return res 72 } 73 74 type FileSearch interface { 75 Find(from string, r *regexp.Regexp, typ string) ([]string, error) 76 } 77 78 type PerfStats struct { 79 Start time.Time `json:"start"` 80 Duration time.Duration `json:"duration"` 81 } 82 83 type FileInfo struct { 84 FName string 85 FSize int64 86 FIsDir bool 87 FModTime time.Time 88 FMode os.FileMode 89 Uid int64 90 Gid int64 91 } 92 93 func (f *FileInfo) Name() string { 94 return f.FName 95 } 96 97 func (f *FileInfo) Size() int64 { 98 return f.FSize 99 } 100 101 func (f *FileInfo) Mode() os.FileMode { 102 return f.FMode 103 } 104 105 func (f *FileInfo) ModTime() time.Time { 106 return f.FModTime 107 } 108 109 func (f *FileInfo) IsDir() bool { 110 return f.FIsDir 111 } 112 113 func (f *FileInfo) Sys() interface{} { 114 return f 115 } 116 117 type FileInfoDetails struct { 118 Size int64 119 Mode FileModeDetails 120 Uid int64 121 Gid int64 122 } 123 124 type FileModeDetails struct { 125 os.FileMode 126 } 127 128 func (mode FileModeDetails) UserReadable() bool { 129 return uint32(mode.FileMode)&0o0400 != 0 130 } 131 132 func (mode FileModeDetails) UserWriteable() bool { 133 return uint32(mode.FileMode)&0o0200 != 0 134 } 135 136 func (mode FileModeDetails) UserExecutable() bool { 137 return uint32(mode.FileMode)&0o0100 != 0 138 } 139 140 func (mode FileModeDetails) GroupReadable() bool { 141 return uint32(mode.FileMode)&0o0040 != 0 142 } 143 144 func (mode FileModeDetails) GroupWriteable() bool { 145 return uint32(mode.FileMode)&0o0020 != 0 146 } 147 148 func (mode FileModeDetails) GroupExecutable() bool { 149 return uint32(mode.FileMode)&0o0010 != 0 150 } 151 152 func (mode FileModeDetails) OtherReadable() bool { 153 return uint32(mode.FileMode)&0o0004 != 0 154 } 155 156 func (mode FileModeDetails) OtherWriteable() bool { 157 return uint32(mode.FileMode)&0o0002 != 0 158 } 159 160 func (mode FileModeDetails) OtherExecutable() bool { 161 return uint32(mode.FileMode)&0o0001 != 0 162 } 163 164 func (mode FileModeDetails) Suid() bool { 165 return mode.FileMode&fs.ModeSetuid != 0 166 } 167 168 func (mode FileModeDetails) Sgid() bool { 169 return mode.FileMode&fs.ModeSetgid != 0 170 } 171 172 func (mode FileModeDetails) Sticky() bool { 173 return mode.FileMode&fs.ModeSticky != 0 174 } 175 176 func (mode FileModeDetails) UnixMode() uint32 { 177 m := mode.FileMode & 0o777 178 179 if mode.IsDir() { 180 } 181 182 if (mode.FileMode & fs.ModeSetuid) != 0 { 183 m |= 0o4000 184 } 185 186 if (mode.FileMode & fs.ModeSetgid) != 0 { 187 m |= 0o2000 188 } 189 190 if (mode.FileMode & fs.ModeSticky) != 0 { 191 m |= 0o1000 192 } 193 194 return uint32(m) 195 } 196 197 func ParseSudo(flags map[string]*llx.Primitive) *inventory.Sudo { 198 sudo := flags["sudo"] 199 if sudo == nil { 200 return nil 201 } 202 203 active := sudo.RawData().Value.(bool) 204 if !active { 205 return nil 206 } 207 208 return &inventory.Sudo{ 209 Active: true, 210 Executable: "sudo", 211 } 212 } 213 214 func BuildSudoCommand(sudo *inventory.Sudo, cmd string) string { 215 var sb strings.Builder 216 217 if sudo == nil || !sudo.Active { 218 return cmd 219 } 220 221 sb.WriteString(sudo.Executable) 222 223 if len(sudo.User) > 0 { 224 sb.WriteString(" -u " + sudo.User) 225 } 226 227 if len(sudo.Shell) > 0 { 228 sb.WriteString(" " + sudo.Shell + " -c " + cmd) 229 } else { 230 sb.WriteString(" ") 231 sb.WriteString(cmd) 232 } 233 234 return sb.String() 235 } 236 237 type Wrapper interface { 238 Build(cmd string) string 239 }