33package repo
44
55import (
6+ "net/url"
67 "os"
78 "path/filepath"
89 "testing"
910
11+ "github.com/go-git/go-git/v5"
1012 "github.com/stretchr/testify/assert"
1113 "github.com/stretchr/testify/require"
1214
@@ -22,7 +24,7 @@ import (
2224)
2325
2426func TestNewArtifact (t * testing.T ) {
25- ts := gittest .NewTestServer (t )
27+ ts := gittest .NewTestServer (t , gittest. Options {} )
2628 defer ts .Close ()
2729
2830 type args struct {
@@ -164,7 +166,7 @@ func TestNewArtifact(t *testing.T) {
164166}
165167
166168func TestArtifact_Inspect (t * testing.T ) {
167- ts := gittest .NewTestServer (t )
169+ ts := gittest .NewTestServer (t , gittest. Options {} )
168170 defer ts .Close ()
169171
170172 tests := []struct {
@@ -330,6 +332,178 @@ func TestArtifact_Inspect(t *testing.T) {
330332 }
331333}
332334
335+ // setupAuthTestServer creates a test server with authentication and returns parsed URL with /test-repo.git path
336+ func setupAuthTestServer (t * testing.T , username , password string ) * url.URL {
337+ t .Helper ()
338+ ts := gittest .NewTestServer (t , gittest.Options {
339+ Username : username ,
340+ Password : password ,
341+ })
342+ t .Cleanup (ts .Close )
343+
344+ tsURL , err := url .Parse (ts .URL )
345+ require .NoError (t , err )
346+ tsURL .Path = "/test-repo.git"
347+
348+ return tsURL
349+ }
350+
351+ // testInspectArtifact is a helper function to inspect an artifact and assert the results
352+ func testInspectArtifact (t * testing.T , target , wantRepoURL , wantErr string ) {
353+ t .Helper ()
354+ art , cleanup , err := NewArtifact (target , cache .NewMemoryCache (), walker .NewFS (), artifact.Option {})
355+ t .Cleanup (cleanup )
356+
357+ if wantErr != "" {
358+ require .ErrorContains (t , err , wantErr )
359+ return
360+ }
361+ require .NoError (t , err )
362+
363+ // Verify Inspect works
364+ ref , err := art .Inspect (t .Context ())
365+ require .NoError (t , err )
366+
367+ // Verify the RepoURL
368+ assert .Equal (t , wantRepoURL , ref .RepoMetadata .RepoURL )
369+
370+ // Verify we have blob IDs (indicating successful scan)
371+ assert .NotEmpty (t , ref .BlobIDs )
372+ }
373+
374+ func TestArtifact_InspectWithAuth (t * testing.T ) {
375+ const (
376+ testUsername = "testuser"
377+ testPassword = "testpass"
378+ )
379+
380+ // Test with environment variable authentication (GITHUB_TOKEN, GITLAB_TOKEN)
381+ t .Run ("environment variable authentication" , func (t * testing.T ) {
382+ const testGitUsername = "fanal-aquasecurity-scan" // This is the username used by Trivy
383+
384+ // Setup test server with authentication
385+ tsURL := setupAuthTestServer (t , testGitUsername , testPassword )
386+
387+ tests := []struct {
388+ name string
389+ target string
390+ envVars map [string ]string
391+ wantErr string
392+ wantRepoURL string
393+ }{
394+ {
395+ name : "success with GITHUB_TOKEN" ,
396+ target : tsURL .String (),
397+ envVars : map [string ]string {
398+ "GITHUB_TOKEN" : testPassword ,
399+ },
400+ wantRepoURL : tsURL .String (),
401+ },
402+ {
403+ name : "success with GITLAB_TOKEN" ,
404+ target : tsURL .String (),
405+ envVars : map [string ]string {
406+ "GITLAB_TOKEN" : testPassword ,
407+ },
408+ wantRepoURL : tsURL .String (),
409+ },
410+ {
411+ name : "failure without token" ,
412+ target : tsURL .String (),
413+ wantErr : "authentication required" ,
414+ },
415+ {
416+ name : "failure with wrong token" ,
417+ target : tsURL .String (),
418+ envVars : map [string ]string {
419+ "GITHUB_TOKEN" : "wrongpassword" ,
420+ },
421+ wantErr : "authentication required" ,
422+ },
423+ }
424+
425+ for _ , tt := range tests {
426+ t .Run (tt .name , func (t * testing.T ) {
427+ // Set test environment variables
428+ for key , value := range tt .envVars {
429+ t .Setenv (key , value )
430+ }
431+
432+ // Test using helper function
433+ testInspectArtifact (t , tt .target , tt .wantRepoURL , tt .wantErr )
434+ })
435+ }
436+ })
437+
438+ // Test with URL-embedded authentication
439+ t .Run ("URL embedded authentication" , func (t * testing.T ) {
440+ // Setup test server with authentication
441+ tsURL := setupAuthTestServer (t , testUsername , testPassword )
442+
443+ // Helper function to generate target URL with credentials
444+ makeTarget := func (username , password string ) string {
445+ u := * tsURL // Copy the URL
446+ if username != "" && password != "" {
447+ u .User = url .UserPassword (username , password )
448+ }
449+ return u .String ()
450+ }
451+
452+ tests := []struct {
453+ name string
454+ target string
455+ wantRepoURL string
456+ wantErr string
457+ }{
458+ {
459+ name : "success with embedded credentials" ,
460+ target : makeTarget (testUsername , testPassword ),
461+ wantRepoURL : makeTarget (testUsername , testPassword ), // TODO: username/password should be stripped
462+ },
463+ {
464+ name : "failure with wrong password" ,
465+ target : makeTarget (testUsername , "wrongpass" ),
466+ wantErr : "authentication required" ,
467+ },
468+ {
469+ name : "failure without credentials" ,
470+ target : makeTarget ("" , "" ),
471+ wantErr : "authentication required" ,
472+ },
473+ }
474+
475+ for _ , tt := range tests {
476+ t .Run (tt .name , func (t * testing.T ) {
477+ // Test using helper function
478+ testInspectArtifact (t , tt .target , tt .wantRepoURL , tt .wantErr )
479+ })
480+ }
481+ })
482+
483+ // Test cloning with embedded credentials and then scanning the local directory
484+ t .Run ("clone with credentials then scan local" , func (t * testing.T ) {
485+ // Setup test server with authentication
486+ tsURL := setupAuthTestServer (t , testUsername , testPassword )
487+
488+ // Add credentials to URL
489+ tsURL .User = url .UserPassword (testUsername , testPassword )
490+ targetWithCreds := tsURL .String ()
491+
492+ // Clone the repository with URL-embedded credentials
493+ cloneDir := filepath .Join (t .TempDir (), "cloned-repo" )
494+
495+ // Use go-git directly to clone with URL-embedded credentials
496+ _ , err := git .PlainClone (cloneDir , false , & git.CloneOptions {
497+ URL : targetWithCreds ,
498+ })
499+ require .NoError (t , err )
500+
501+ // Scan and verify the local cloned directory
502+ // TODO: The credentials in the URL should be stripped in the RepoURL
503+ testInspectArtifact (t , cloneDir , targetWithCreds , "" )
504+ })
505+ }
506+
333507func Test_newURL (t * testing.T ) {
334508 type args struct {
335509 rawurl string
0 commit comments