github.com/google/osv-scalibr@v0.4.1/extractor/filesystem/secrets/pgpass/pgpass_test.go (about)

     1  // Copyright 2025 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package pgpass_test
    16  
    17  import (
    18  	"testing"
    19  
    20  	"github.com/google/go-cmp/cmp"
    21  	"github.com/google/osv-scalibr/extractor/filesystem"
    22  	"github.com/google/osv-scalibr/extractor/filesystem/secrets/pgpass"
    23  	"github.com/google/osv-scalibr/extractor/filesystem/simplefileapi"
    24  	"github.com/google/osv-scalibr/inventory"
    25  	"github.com/google/osv-scalibr/testing/extracttest"
    26  )
    27  
    28  func TestFileRequired(t *testing.T) {
    29  	tests := []struct {
    30  		name         string
    31  		path         string
    32  		wantRequired bool
    33  	}{
    34  		{
    35  			name:         "valid .pgpass",
    36  			path:         "/foo/.pgpass",
    37  			wantRequired: true,
    38  		},
    39  		{
    40  			name:         "valid .pgpass",
    41  			path:         ".pgpass",
    42  			wantRequired: true,
    43  		},
    44  		{
    45  			name:         "invalid .pgpass",
    46  			path:         "/foo.pgpass",
    47  			wantRequired: false,
    48  		},
    49  		{
    50  			name:         "invalid .pgpass",
    51  			path:         "/foo.pgpass.ext",
    52  			wantRequired: false,
    53  		},
    54  		{
    55  			name:         "invalid .pgpass",
    56  			path:         "/foo_pgpass_zoo.ext",
    57  			wantRequired: false,
    58  		},
    59  	}
    60  
    61  	for _, tt := range tests {
    62  		t.Run(tt.name, func(t *testing.T) {
    63  			var e filesystem.Extractor = pgpass.Extractor{}
    64  			if got := e.FileRequired(simplefileapi.New(tt.path, nil)); got != tt.wantRequired {
    65  				t.Fatalf("FileRequired(%s): got %v, want %v", tt.path, got, tt.wantRequired)
    66  			}
    67  		})
    68  	}
    69  }
    70  
    71  func TestExtract(t *testing.T) {
    72  	tests := []struct {
    73  		Name        string
    74  		InputConfig extracttest.ScanInputMockConfig
    75  		WantSecrets []*inventory.Secret
    76  		WantErr     error
    77  	}{
    78  		{
    79  			Name: "valid .pgpass file",
    80  			InputConfig: extracttest.ScanInputMockConfig{
    81  				Path: "testdata/valid",
    82  			},
    83  			WantSecrets: []*inventory.Secret{
    84  				{
    85  					Secret: pgpass.Pgpass{Hostname: "localhost",
    86  						Port:     "5432",
    87  						Database: "mydb",
    88  						Username: "myuser",
    89  						Password: "mypassword"},
    90  					Location: "testdata/valid",
    91  				},
    92  				{
    93  					Secret: pgpass.Pgpass{Hostname: "hostname",
    94  						Port:     "1234",
    95  						Database: "testdb",
    96  						Username: "testuser",
    97  						Password: "testpass123"},
    98  					Location: "testdata/valid",
    99  				},
   100  				{
   101  					Secret: pgpass.Pgpass{Hostname: "hostname",
   102  						Port:     "1234",
   103  						Database: "testdb",
   104  						Username: "testuser",
   105  						Password: "passw*ord"},
   106  					Location: "testdata/valid",
   107  				},
   108  				{
   109  					Secret: pgpass.Pgpass{Hostname: "hostname",
   110  						Port:     "1234",
   111  						Database: "testdb",
   112  						Username: "testuser",
   113  						Password: "passw ord"},
   114  					Location: "testdata/valid",
   115  				},
   116  				{
   117  					Secret: pgpass.Pgpass{Hostname: "hostname",
   118  						Port:     "1234",
   119  						Database: "db name",
   120  						Username: "testuser",
   121  						Password: "password"},
   122  					Location: "testdata/valid",
   123  				},
   124  				{
   125  					Secret: pgpass.Pgpass{Hostname: "*",
   126  						Port:     "*",
   127  						Database: "db",
   128  						Username: "admin",
   129  						Password: "supersecret"},
   130  					Location: "testdata/valid",
   131  				},
   132  				{
   133  					Secret: pgpass.Pgpass{Hostname: "prod.example.com",
   134  						Port:     "5432",
   135  						Database: "db",
   136  						Username: "admin",
   137  						Password: `pass\:word`},
   138  					Location: "testdata/valid",
   139  				},
   140  			},
   141  		}, {
   142  			Name: "invalid .pgpass file",
   143  			InputConfig: extracttest.ScanInputMockConfig{
   144  				Path: "testdata/invalid",
   145  			},
   146  			WantSecrets: nil,
   147  		},
   148  	}
   149  
   150  	for _, tt := range tests {
   151  		t.Run(tt.Name, func(t *testing.T) {
   152  			e := pgpass.New()
   153  			scanInput := extracttest.GenerateScanInputMock(t, tt.InputConfig)
   154  			defer extracttest.CloseTestScanInput(t, scanInput)
   155  
   156  			got, err := e.Extract(t.Context(), &scanInput)
   157  			if err != nil {
   158  				t.Fatalf("%s.Extract(%q) failed: %v", e.Name(), tt.InputConfig.Path, err)
   159  			}
   160  
   161  			wantInv := inventory.Inventory{Secrets: tt.WantSecrets}
   162  			if diff := cmp.Diff(wantInv, got); diff != "" {
   163  				t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", e.Name(), tt.InputConfig.Path, diff)
   164  			}
   165  		})
   166  	}
   167  }