@@ -11,7 +11,6 @@ import (
1111 "time"
1212
1313 "github.com/go-errors/errors"
14- "github.com/go-logr/logr"
1514 "github.com/trufflesecurity/trufflehog/v3/pkg/log"
1615 "google.golang.org/protobuf/proto"
1716 "google.golang.org/protobuf/types/known/anypb"
@@ -37,7 +36,6 @@ type Source struct {
3736 user string
3837 token string
3938 header * header
40- log logr.Logger
4139 client * http.Client
4240 sources.Progress
4341}
@@ -66,8 +64,6 @@ func (s *Source) JobID() sources.JobID {
6664
6765// Init returns an initialized Jenkins source.
6866func (s * Source ) Init (aCtx context.Context , name string , jobId sources.JobID , sourceId sources.SourceID , verify bool , connection * anypb.Any , _ int ) error {
69- s .log = aCtx .Logger ()
70-
7167 s .name = name
7268 s .sourceId = sourceId
7369 s .jobId = jobId
@@ -89,7 +85,7 @@ func (s *Source) Init(aCtx context.Context, name string, jobId sources.JobID, so
8985
9086 const retryDelay = time .Second * 30
9187 opts = append (opts ,
92- roundtripper .WithLogger (s . log ),
88+ roundtripper .WithLogger (aCtx . Logger () ),
9389 roundtripper .WithLogging (),
9490 roundtripper .WithRetryable (
9591 roundtripper .WithShouldRetry5XXDuration (retryDelay ),
@@ -104,6 +100,7 @@ func (s *Source) Init(aCtx context.Context, name string, jobId sources.JobID, so
104100 s .client = client
105101
106102 var unparsedURL string
103+ var authMethod string
107104 switch cred := conn .GetCredential ().(type ) {
108105 case * sourcespb.Jenkins_BasicAuth :
109106 unparsedURL = conn .Endpoint
@@ -113,15 +110,18 @@ func (s *Source) Init(aCtx context.Context, name string, jobId sources.JobID, so
113110 return errors .Errorf ("Jenkins source basic auth credential requires 'password' to be specified" )
114111 }
115112 log .RedactGlobally (s .token )
113+ authMethod = "basic"
116114 case * sourcespb.Jenkins_Header :
117115 unparsedURL = conn .Endpoint
118116 s .header = & header {
119117 key : cred .Header .Key ,
120118 value : cred .Header .Value ,
121119 }
122120 log .RedactGlobally (cred .Header .GetValue ())
121+ authMethod = "header"
123122 case * sourcespb.Jenkins_Unauthenticated :
124123 unparsedURL = conn .Endpoint
124+ authMethod = "none"
125125 default :
126126 return errors .Errorf ("unknown or unspecified authentication method provided for Jenkins source %q (unauthenticated scans must be explicitly configured)" , name )
127127 }
@@ -131,6 +131,11 @@ func (s *Source) Init(aCtx context.Context, name string, jobId sources.JobID, so
131131 return errors .WrapPrefix (err , fmt .Sprintf ("Invalid endpoint URL given for Jenkins source: %s" , unparsedURL ), 0 )
132132 }
133133
134+ aCtx .Logger ().V (1 ).Info ("initialized Jenkins source" ,
135+ "auth_method" , authMethod ,
136+ "url_raw" , unparsedURL ,
137+ "url_parsed" , s .url .String ())
138+
134139 return nil
135140}
136141
@@ -187,13 +192,24 @@ func (s *Source) GetJenkinsJobs(ctx context.Context) (JenkinsJobResponse, error)
187192}
188193
189194func (s * Source ) RecursivelyGetJenkinsObjectsForPath (ctx context.Context , absolutePath string ) (JenkinsJobResponse , error ) {
195+ ctx .Logger ().V (3 ).Info ("getting objects" ,
196+ "path" , absolutePath )
197+
190198 jobs := JenkinsJobResponse {}
191199 objects , err := s .GetJenkinsObjectsForPath (ctx , absolutePath )
192200 if err != nil {
193201 return jobs , err
194202 }
203+ ctx .Logger ().V (3 ).Info ("got objects" ,
204+ "path" , absolutePath ,
205+ "count" , len (objects .Jobs ))
195206
196207 for _ , job := range objects .Jobs {
208+ ctx .Logger ().V (3 ).Info ("processing object" ,
209+ "object_name" , job .Name ,
210+ "object_class" , job .Class ,
211+ "object_url" , job .Url )
212+
197213 if job .Class == "com.cloudbees.hudson.plugins.folder.Folder" {
198214 u , err := url .Parse (job .Url )
199215 if err != nil {
@@ -221,6 +237,7 @@ func (s *Source) GetJenkinsObjectsForPath(ctx context.Context, absolutePath stri
221237 baseUrl .Path = path .Join (absolutePath , "api/json" )
222238 baseUrl .RawQuery = fmt .Sprintf ("tree=jobs[name,url]{%d,%d}" , i , i + 100 )
223239
240+ ctx .Logger ().V (4 ).Info ("executing query" , "query_url" , baseUrl .String ())
224241 req , err := s .NewRequest (http .MethodGet , baseUrl .String (), nil )
225242 if err != nil {
226243 return res , errors .WrapPrefix (err , "Failed to create new request to get jenkins jobs" , 0 )
@@ -255,6 +272,11 @@ func (s *Source) GetJenkinsObjectsForPath(ctx context.Context, absolutePath stri
255272}
256273
257274func (s * Source ) GetJenkinsBuilds (ctx context.Context , jobAbsolutePath string ) (JenkinsBuildResponse , error ) {
275+ ctx = context .WithValues (ctx ,
276+ "job_path" , jobAbsolutePath )
277+
278+ ctx .Logger ().V (2 ).Info ("getting builds" )
279+
258280 builds := JenkinsBuildResponse {}
259281 buildsUrl := * s .url
260282 for i := 0 ; true ; i += 100 {
@@ -265,6 +287,7 @@ func (s *Source) GetJenkinsBuilds(ctx context.Context, jobAbsolutePath string) (
265287 return builds , errors .WrapPrefix (err , "Failed to create new request to get jenkins builds" , 0 )
266288 }
267289
290+ ctx .Logger ().V (4 ).Info ("executing query" , "query_url" , req .URL .String ())
268291 resp , err := s .client .Do (req )
269292 if err != nil {
270293 return builds , errors .WrapPrefix (err , "Failed to do get jenkins builds request" , 0 )
@@ -299,34 +322,48 @@ func (s *Source) Chunks(ctx context.Context, chunksChan chan *sources.Chunk, _ .
299322 if err != nil {
300323 return errors .WrapPrefix (err , "Failed to get Jenkins job response" , 0 )
301324 }
325+ ctx .Logger ().V (1 ).Info ("got jobs" , "count" , len (jobs .Jobs ))
302326
303327 for i , project := range jobs .Jobs {
304328 if common .IsDone (ctx ) {
305329 return nil
306330 }
307331
332+ ctx := context .WithValues (ctx ,
333+ "job_name" , project .Name ,
334+ "job_class" , project .Class ,
335+ "job_url" , project .Url )
336+
308337 s .SetProgressComplete (i , len (jobs .Jobs ), fmt .Sprintf ("Project: %s" , project .Name ), "" )
309338
310339 parsedUrl , err := url .Parse (project .Url )
311340 if err != nil {
312- s . log .Error (err , "Failed to parse Jenkins project URL, skipping project" , "url" , project . Url , "project" , project . Name )
341+ ctx . Logger () .Error (err , "failed to parse job URL; skipping job" )
313342 continue
314343 }
315344 projectURL := * s .url
316345 projectURL .Path = parsedUrl .Path
317346
318347 builds , err := s .GetJenkinsBuilds (ctx , projectURL .Path )
319348 if err != nil {
320- s . log .Error (err , "Failed to get Jenkins build response, skipping project" , "project" , project . Name )
349+ ctx . Logger () .Error (err , "failed to get builds; skipping job" )
321350 continue
322351 }
352+ ctx .Logger ().V (2 ).Info ("got builds" ,
353+ "count" , len (builds .Builds ))
323354
324355 for _ , build := range builds .Builds {
325356 if common .IsDone (ctx ) {
326357 return nil
327358 }
328359
329- s .chunkBuild (ctx , build , project .Name , chunksChan )
360+ ctx := context .WithValues (ctx ,
361+ "build_number" , build .Number ,
362+ "build_url" , build .Url )
363+
364+ if err := s .chunkBuild (ctx , build , project .Name , chunksChan ); err != nil {
365+ ctx .Logger ().Error (err , "error scanning build log" )
366+ }
330367 }
331368 }
332369
@@ -336,45 +373,46 @@ func (s *Source) Chunks(ctx context.Context, chunksChan chan *sources.Chunk, _ .
336373
337374// chunkBuild takes build information and sends it to the chunksChan.
338375// It also logs all errors that occur and does not return them, as the parent context expects to continue running.
339- func (s * Source ) chunkBuild (_ context.Context , build JenkinsBuild , projectName string , chunksChan chan * sources.Chunk ) {
340- // Setup a logger to identify the build and project.
341- chunkBuildLog := s .log .WithValues (
342- "build" , build .Number ,
343- "project" , projectName ,
344- )
376+ func (s * Source ) chunkBuild (
377+ ctx context.Context ,
378+ build JenkinsBuild ,
379+ projectName string ,
380+ chunksChan chan * sources.Chunk ,
381+ ) error {
382+ ctx .Logger ().V (2 ).Info ("chunking build" )
345383
346384 parsedUrl , err := url .Parse (build .Url )
347385 if err != nil {
348- chunkBuildLog .Error (err , "Failed to parse Jenkins build URL, skipping build" , "url" , build .Url )
349- return
386+ return fmt .Errorf ("failed to parse build URL %q: %w" , build .Url , err )
350387 }
351388 buildLogURL := * s .url
352389 buildLogURL .Path = path .Join (parsedUrl .Path , "consoleText" )
390+ ctx = context .WithValues (ctx ,
391+ "build_log_url" , buildLogURL .String ())
353392
354393 req , err := s .NewRequest (http .MethodGet , buildLogURL .String (), nil )
355394 if err != nil {
356- chunkBuildLog .Error (err , "Failed to create new request to Jenkins, skipping build" )
357- return
395+ return fmt .Errorf ("failed to create HTTP request to %q: %w" , buildLogURL .String (), err )
358396 }
359397
360398 resp , err := s .client .Do (req )
361399 if err != nil {
362- chunkBuildLog .Error (err , "Failed to get build log in Jenkins chunks, skipping build" )
363- return
400+ return fmt .Errorf ("could not retrieve build log from %q: %w" , buildLogURL .String (), err )
364401 }
365402 defer resp .Body .Close ()
366403
367404 if resp .StatusCode >= 400 {
368- chunkBuildLog .Error (err , "Status Code from build was unexpected, skipping build" , "status_code" , resp .StatusCode )
369- return
405+ return fmt .Errorf ("got unexpected HTTP status code %v when trying to retrieve build log from %q" ,
406+ resp .StatusCode ,
407+ buildLogURL .String ())
370408 }
371409
372410 buildLog , err := io .ReadAll (resp .Body )
373411 if err != nil {
374- chunkBuildLog .Error (err , "Failed to read body from the build log response, skipping build" )
375- return
412+ return fmt .Errorf ("error reading build log response body from %q: %w" , buildLogURL .String (), err )
376413 }
377414
415+ ctx .Logger ().V (4 ).Info ("scanning build log" )
378416 chunksChan <- & sources.Chunk {
379417 SourceName : s .name ,
380418 SourceID : s .SourceID (),
@@ -392,6 +430,8 @@ func (s *Source) chunkBuild(_ context.Context, build JenkinsBuild, projectName s
392430 Data : buildLog ,
393431 Verify : s .verify ,
394432 }
433+
434+ return nil
395435}
396436
397437type JenkinsJobResponse struct {
0 commit comments