github.com/google/osv-scalibr@v0.4.1/extractor/filesystem/secrets/onepasswordconnecttoken/onepasswordconnecttoken_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 onepasswordconnecttoken_test 16 17 import ( 18 "testing" 19 20 "github.com/google/go-cmp/cmp" 21 "github.com/google/go-cmp/cmp/cmpopts" 22 "github.com/google/osv-scalibr/extractor/filesystem/secrets/onepasswordconnecttoken" 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 onepassword json file", 36 path: "/project/onepassword-token.json", 37 wantRequired: true, 38 }, 39 { 40 name: "valid 1password json file", 41 path: "/project/1password-config.json", 42 wantRequired: true, 43 }, 44 { 45 name: "onepassword uppercase", 46 path: "/project/ONEPASSWORD-settings.json", 47 wantRequired: true, 48 }, 49 { 50 name: "invalid extension", 51 path: "/project/onepassword-token.txt", 52 wantRequired: false, 53 }, 54 { 55 name: "no onepassword in name", 56 path: "/project/config.json", 57 wantRequired: false, 58 }, 59 { 60 name: "not json file", 61 path: "/tmp/var/scalibr", 62 wantRequired: false, 63 }, 64 } 65 for _, tt := range tests { 66 t.Run(tt.name, func(t *testing.T) { 67 e := onepasswordconnecttoken.Extractor{} 68 if got := e.FileRequired(simplefileapi.New(tt.path, nil)); got != tt.wantRequired { 69 t.Fatalf("FileRequired(%s): got %v, want %v", tt.path, got, tt.wantRequired) 70 } 71 }) 72 } 73 } 74 75 func TestExtract(t *testing.T) { 76 tests := []struct { 77 name string 78 wantSecrets []*inventory.Secret 79 inputConfigFile extracttest.ScanInputMockConfig 80 }{ 81 { 82 name: "valid_onepassword_connect_token", 83 inputConfigFile: extracttest.ScanInputMockConfig{ 84 Path: "testdata/valid", 85 }, 86 wantSecrets: []*inventory.Secret{ 87 { 88 Secret: onepasswordconnecttoken.OnePasswordConnectToken{ 89 DeviceUUID: "yrkdmusoblmgm6siuj4kcssxke", 90 Version: "2", 91 EncryptedData: "yQVzCjBZa5mRMHsT5DQF9y9NWR0oY1ZudueqUCuKEUm4agXFGagMLiZJgwX4zn8nCfhtEWgA0OUo10HlR-oMx6hpHw8QsW8Y3e61t0en40LHAzMwjIZtIn_NFKAzSAMJRU3sv4Kz70YsZZopK9Jsgx4czkCcYqgr-3KxVczVpBhsq6PhPYh-xsr8a2tDQ2_ZWYQgTyUH51vV0ZfNOH81Wa6M6Xc2uAtBLx3uxP7odK0h1CH6RhEmokX1lwPy8C5d0wKRF-DJGpzEUZ9wenic8BtDVO00rAOQJT1sUZM6YHPcxL6mco3kWhuXtPVHBcWbDPWWK-WHoRTI_qUKBg3yof-19Y9DBwT2ScwBFbssZgCcQ7pXy8GK_VP0n381zMDbD5w0ZD3qA58jYWTK36_ZWkbcFv_jG1rvk1O5DuGnlQT3cQxv9ELUKT6FB9qqvGjvkWZzKDfljHQ7QThlOzG5iVFYkWKXEAW60BOQmRwI4xikrPvf3KjywE2IFxliUWxt5AMHSWrknyEoHSLkpSThLDL4EhePptc9UBW6rkYhVsC6ZUkiOIIQ1hOBPRqctAteacuCGD1I9CI3x5CgnEL7TNPX_njDO_fkvQBJUBauLaPP7ObjyPDnWLOAKROELWjrFA", 92 EncryptionKeyID: "localauthv2keykid", 93 IV: "nHE-eIYl0_YgVo14", 94 UniqueKeyID: "pol5dybe7lxax42ha6r7rwwdm4", 95 VerifierSalt: "JD6cq4PDx8biZ_WIEo8sJQ", 96 VerifierLocalHash: "lLjGM419fBfty9S-a7BwXBLsl40QL0xWmReBF2r9hM8", 97 }, 98 Location: "testdata/valid", 99 }, 100 }, 101 }, 102 { 103 name: "invalid_json", 104 inputConfigFile: extracttest.ScanInputMockConfig{ 105 Path: "testdata/invalid", 106 }, 107 wantSecrets: nil, 108 }, 109 { 110 name: "missing_required_fields", 111 inputConfigFile: extracttest.ScanInputMockConfig{ 112 Path: "testdata/incomplete", 113 }, 114 wantSecrets: nil, 115 }, 116 } 117 118 for _, tt := range tests { 119 t.Run(tt.name, func(t *testing.T) { 120 extr := onepasswordconnecttoken.Extractor{} 121 122 scanInput := extracttest.GenerateScanInputMock(t, tt.inputConfigFile) 123 defer extracttest.CloseTestScanInput(t, scanInput) 124 125 got, err := extr.Extract(t.Context(), &scanInput) 126 if err != nil { 127 t.Fatalf("Extract() unexpected error = %v", err) 128 } 129 130 if tt.wantSecrets == nil { 131 // For invalid cases, we expect empty inventory 132 wantInv := inventory.Inventory{} 133 if diff := cmp.Diff(wantInv, got); diff != "" { 134 t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.inputConfigFile.Path, diff) 135 } 136 return 137 } 138 139 wantInv := inventory.Inventory{Secrets: tt.wantSecrets} 140 if diff := cmp.Diff(wantInv, got, cmpopts.IgnoreUnexported(onepasswordconnecttoken.OnePasswordConnectToken{})); diff != "" { 141 t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.inputConfigFile.Path, diff) 142 } 143 }) 144 } 145 }