44 "bytes"
55 "context"
66 "encoding/base64"
7- "encoding/json"
87 "fmt"
98 "github.com/murphysecurity/murphysec/errors"
109 "github.com/murphysecurity/murphysec/infra/logctx"
@@ -13,7 +12,6 @@ import (
1312 "go.uber.org/zap"
1413 "io"
1514 "math/rand"
16- "net/url"
1715 "os"
1816 "os/exec"
1917 "path/filepath"
@@ -116,41 +114,30 @@ func ExecuteConanInfoCmd(ctx context.Context, cmdInfo *CmdInfo, dir string) (str
116114 }
117115 jsonP := getConanInfoJsonPath ()
118116 major := ConanMajorVersion (cmdInfo .Version )
119- remoteCreds , credErr := getConanRemoteCredentialsFromConfig (major )
120- if credErr != nil {
121- logger .Warn ("Conan remote credential precheck failed when reading config" , zap .Error (credErr ))
122- }
123117 logger .Sugar ().Infof ("Conan detected: path=%s version=%s major=%d" , cmdInfo .Path , cmdInfo .Version , major )
124118 logger .Sugar ().Infof ("Conan verbose mode: -v %s" , conanVerboseArg )
125119 logConanRemoteConfigPaths (logger , major )
126- loginWarnings := ensureConanRemoteLogin (ctx , cmdInfo .Path , major , remoteCreds )
127120 logger .Sugar ().Debugf ("temp file: %s" , jsonP )
128121 if major >= 2 {
129- if e := ensureConan2DefaultProfile (ctx , cmdInfo .Path , major , remoteCreds ); e != nil {
122+ if e := ensureConan2DefaultProfile (ctx , cmdInfo .Path ); e != nil {
130123 return "" , "" , e
131124 }
132125 logger .Info ("Conan mode selected: graph" )
133- if e := executeConanGraphInfoCmd (ctx , cmdInfo .Path , dir , jsonP , major , remoteCreds ); e != nil {
134- if len (loginWarnings ) > 0 {
135- return "" , "" , fmt .Errorf ("%w; login warnings: %s" , e , strings .Join (loginWarnings , " | " ))
136- }
126+ if e := executeConanGraphInfoCmd (ctx , cmdInfo .Path , dir , jsonP ); e != nil {
137127 return "" , "" , e
138128 }
139129 logger .Info ("Conan command completed with graph mode" )
140130 return jsonP , ConanJsonKindGraph , nil
141131 }
142132 logger .Info ("Conan mode selected: info" )
143- if e := executeConanInfoCmd (ctx , cmdInfo .Path , dir , jsonP , major , remoteCreds ); e != nil {
144- if len (loginWarnings ) > 0 {
145- return "" , "" , fmt .Errorf ("%w; login warnings: %s" , e , strings .Join (loginWarnings , " | " ))
146- }
133+ if e := executeConanInfoCmd (ctx , cmdInfo .Path , dir , jsonP ); e != nil {
147134 return "" , "" , e
148135 }
149136 logger .Info ("Conan command completed with info mode" )
150137 return jsonP , ConanJsonKindInfo , nil
151138}
152139
153- func ensureConan2DefaultProfile (ctx context.Context , conanPath string , major int , remoteCreds [] conanRemoteCredential ) error {
140+ func ensureConan2DefaultProfile (ctx context.Context , conanPath string ) error {
154141 logger := logctx .Use (ctx )
155142 home , err := os .UserHomeDir ()
156143 if err != nil || home == "" {
@@ -166,10 +153,10 @@ func ensureConan2DefaultProfile(ctx context.Context, conanPath string, major int
166153 }
167154
168155 logger .Sugar ().Infof ("Conan default profile missing: %s, running detect" , profilePath )
169- args := conanArgs (major , "profile" , "detect" , "--force" )
156+ args := conanArgs ("profile" , "detect" , "--force" )
170157 c := exec .CommandContext (ctx , conanPath , args ... )
171158 logger .Sugar ().Infof ("Command: %s" , c .String ())
172- c .Env = getEnvForConan (major , remoteCreds )
159+ c .Env = getEnvForConan ()
173160 start := time .Now ()
174161 sb := suffixbuf .NewSize (1024 )
175162 logPipe := logpipe .New (logger , "conan" )
@@ -189,12 +176,12 @@ func ensureConan2DefaultProfile(ctx context.Context, conanPath string, major int
189176 return nil
190177}
191178
192- func executeConanInfoCmd (ctx context.Context , conanPath string , dir string , jsonP string , major int , remoteCreds [] conanRemoteCredential ) error {
179+ func executeConanInfoCmd (ctx context.Context , conanPath string , dir string , jsonP string ) error {
193180 logger := logctx .Use (ctx )
194- args := conanArgs (major , "info" , "." , "-j" , jsonP )
181+ args := conanArgs ("info" , "." , "-j" , jsonP )
195182 c := exec .Command (conanPath , args ... )
196183 logger .Sugar ().Infof ("Command: %s" , c .String ())
197- c .Env = getEnvForConan (major , remoteCreds )
184+ c .Env = getEnvForConan ()
198185 c .Dir = dir
199186 start := time .Now ()
200187 sb := suffixbuf .NewSize (1024 )
@@ -210,12 +197,12 @@ func executeConanInfoCmd(ctx context.Context, conanPath string, dir string, json
210197 return nil
211198}
212199
213- func executeConanGraphInfoCmd (ctx context.Context , conanPath string , dir string , jsonP string , major int , remoteCreds [] conanRemoteCredential ) error {
200+ func executeConanGraphInfoCmd (ctx context.Context , conanPath string , dir string , jsonP string ) error {
214201 logger := logctx .Use (ctx )
215- args := conanArgs (major , "graph" , "info" , "." , "--format=json" )
202+ args := conanArgs ("graph" , "info" , "." , "--format=json" )
216203 c := exec .Command (conanPath , args ... )
217204 logger .Sugar ().Infof ("Command: %s" , c .String ())
218- c .Env = getEnvForConan (major , remoteCreds )
205+ c .Env = getEnvForConan ()
219206 c .Dir = dir
220207 start := time .Now ()
221208 sb := suffixbuf .NewSize (1024 )
@@ -235,105 +222,7 @@ func executeConanGraphInfoCmd(ctx context.Context, conanPath string, dir string,
235222 return nil
236223}
237224
238- type conanRemoteCredential struct {
239- Name string
240- Username string
241- Password string
242- }
243-
244- func ensureConanRemoteLogin (ctx context.Context , conanPath string , major int , creds []conanRemoteCredential ) []string {
245- warnings := make ([]string , 0 )
246- if major < 2 {
247- return warnings
248- }
249- logger := logctx .Use (ctx )
250- if len (creds ) == 0 {
251- logger .Info ("Conan remote login skipped: no credentials found in remote URLs" )
252- return warnings
253- }
254- for _ , cred := range creds {
255- args := conanArgs (major , "remote" , "auth" , cred .Name , "--force" )
256- c := exec .CommandContext (ctx , conanPath , args ... )
257- c .Env = getEnvForConan (major , []conanRemoteCredential {cred })
258- sb := suffixbuf .NewSize (1024 )
259- logPipe := logpipe .New (logger , "conan" )
260- logger .Sugar ().Infof ("Command: %s remote auth %s --force (credentials from env)" , conanPath , cred .Name )
261- c .Stdout = io .MultiWriter (sb , logPipe )
262- c .Stderr = io .MultiWriter (sb , logPipe )
263- if runErr := c .Run (); runErr != nil {
264- logPipe .Close ()
265- msg := fmt .Sprintf ("conan remote auth failed for %s(user=%s): %v, details: %s" , cred .Name , cred .Username , runErr , strings .TrimSpace (string (sb .Bytes ())))
266- logger .Warn (msg )
267- warnings = append (warnings , msg )
268- continue
269- }
270- logPipe .Close ()
271- logger .Sugar ().Infof ("Conan remote auth completed: remote=%s user=%s" , cred .Name , cred .Username )
272- }
273- return warnings
274- }
275-
276- type conanRemotesFile struct {
277- Remotes []struct {
278- Name string `json:"name"`
279- URL string `json:"url"`
280- } `json:"remotes"`
281- }
282-
283- func getConanRemoteCredentialsFromConfig (major int ) ([]conanRemoteCredential , error ) {
284- path , err := conanRemotesConfigPath (major )
285- if err != nil {
286- return nil , err
287- }
288- data , err := os .ReadFile (path )
289- if err != nil {
290- return nil , err
291- }
292- var cfg conanRemotesFile
293- if err = json .Unmarshal (data , & cfg ); err != nil {
294- return nil , fmt .Errorf ("parse remotes config failed: %w" , err )
295- }
296- rs := make ([]conanRemoteCredential , 0 )
297- seen := make (map [string ]struct {})
298- for _ , remote := range cfg .Remotes {
299- u , parseErr := url .Parse (strings .TrimSpace (remote .URL ))
300- if parseErr != nil || u .User == nil {
301- continue
302- }
303- username := u .User .Username ()
304- password , ok := u .User .Password ()
305- if username == "" || ! ok || password == "" {
306- continue
307- }
308- key := remote .Name + "|" + username
309- if _ , exists := seen [key ]; exists {
310- continue
311- }
312- seen [key ] = struct {}{}
313- rs = append (rs , conanRemoteCredential {
314- Name : remote .Name ,
315- Username : username ,
316- Password : password ,
317- })
318- }
319- return rs , nil
320- }
321-
322- func conanRemotesConfigPath (major int ) (string , error ) {
323- home , err := os .UserHomeDir ()
324- if err != nil || home == "" {
325- return "" , fmt .Errorf ("cannot determine user home: %w" , err )
326- }
327- if major >= 2 {
328- return filepath .Join (home , ".conan2" , "remotes.json" ), nil
329- }
330- return filepath .Join (home , ".conan" , "remotes.json" ), nil
331- }
332-
333- func conanArgs (major int , args ... string ) []string {
334- if major >= 2 {
335- args = append (args , "-cc" , "core:non_interactive=True" )
336- }
225+ func conanArgs (args ... string ) []string {
337226 return append (args , "-v" , conanVerboseArg )
338227}
339228
@@ -351,7 +240,7 @@ func LocateConan(ctx context.Context) (string, error) {
351240
352241func GetConanVersion (ctx context.Context , conanPath string ) (string , error ) {
353242 c := exec .CommandContext (ctx , conanPath , "-v" )
354- c .Env = getBaseEnvForConan ()
243+ c .Env = getEnvForConan ()
355244 if data , e := c .Output (); e != nil {
356245 return "" , errors .WithCause (ErrGetConanVersionFail , e )
357246 } else {
@@ -369,46 +258,9 @@ func ConanMajorVersion(version string) int {
369258 return v
370259}
371260
372- func getBaseEnvForConan () []string {
261+ func getEnvForConan () []string {
373262 osEnv := os .Environ ()
374263 var rs = make ([]string , 0 , len (osEnv )+ 3 )
375264 rs = append (rs , osEnv ... )
376265 return append (rs , "CONAN_NON_INTERACTIVE=1" , "NO_COLOR=1" , "CLICOLOR=0" )
377266}
378-
379- func getEnvForConan (major int , remoteCreds []conanRemoteCredential ) []string {
380- rs := getBaseEnvForConan ()
381- if major < 1 || len (remoteCreds ) == 0 {
382- return rs
383- }
384- for _ , cred := range remoteCreds {
385- suffix := conanRemoteEnvVarSuffix (cred .Name )
386- if suffix == "" || cred .Username == "" || cred .Password == "" {
387- continue
388- }
389- rs = append (rs ,
390- fmt .Sprintf ("CONAN_LOGIN_USERNAME_%s=%s" , suffix , cred .Username ),
391- fmt .Sprintf ("CONAN_PASSWORD_%s=%s" , suffix , cred .Password ),
392- )
393- }
394- return rs
395- }
396-
397- func conanRemoteEnvVarSuffix (remoteName string ) string {
398- remoteName = strings .TrimSpace (remoteName )
399- if remoteName == "" {
400- return ""
401- }
402- var b strings.Builder
403- for _ , r := range remoteName {
404- switch {
405- case r >= 'a' && r <= 'z' :
406- b .WriteRune (r - ('a' - 'A' ))
407- case (r >= 'A' && r <= 'Z' ) || (r >= '0' && r <= '9' ):
408- b .WriteRune (r )
409- default :
410- b .WriteRune ('_' )
411- }
412- }
413- return b .String ()
414- }
0 commit comments