onepassword_test.go 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409
  1. /*
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. */
  12. package onepassword
  13. import (
  14. "context"
  15. "fmt"
  16. "reflect"
  17. "testing"
  18. "github.com/1Password/connect-sdk-go/onepassword"
  19. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  20. "k8s.io/utils/pointer"
  21. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  22. esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
  23. fake "github.com/external-secrets/external-secrets/pkg/provider/onepassword/fake"
  24. )
  25. const (
  26. // vaults and items.
  27. myVault, myVaultID = "my-vault", "my-vault-id"
  28. myItem, myItemID = "my-item", "my-item-id"
  29. mySharedVault, mySharedVaultID = "my-shared-vault", "my-shared-vault-id"
  30. mySharedItem, mySharedItemID = "my-shared-item", "my-shared-item-id"
  31. myOtherVault, myOtherVaultID = "my-other-vault", "my-other-vault-id"
  32. myOtherItem, myOtherItemID = "my-other-item", "my-other-item-id"
  33. myNonMatchingVault, myNonMatchingVaultID = "my-non-matching-vault", "my-non-matching-vault-id"
  34. myNonMatchingItem, myNonMatchingItemID = "my-non-matching-item", "my-non-matching-item-id"
  35. // fields and files.
  36. key1, key2, key3, key4 = "key1", "key2", "key3", "key4"
  37. value1, value2, value3, value4 = "value1", "value2", "value3", "value4"
  38. sharedKey1, sharedValue1 = "sharedkey1", "sharedvalue1"
  39. otherKey1 = "otherkey1"
  40. filePNG, filePNGID = "file.png", "file-id"
  41. myFilePNG, myFilePNGID, myContents = "my-file.png", "my-file-id", "my-contents"
  42. mySecondFileTXT, mySecondFileTXTID = "my-second-file.txt", "my-second-file-id"
  43. mySecondContents = "my-second-contents"
  44. myFile2PNG, myFile2TXT = "my-file-2.png", "my-file-2.txt"
  45. myFile2ID, myContents2 = "my-file-2-id", "my-contents-2"
  46. myOtherFilePNG, myOtherFilePNGID = "my-other-file.png", "my-other-file-id"
  47. myOtherContents = "my-other-contents"
  48. nonMatchingFilePNG, nonMatchingFilePNGID = "non-matching-file.png", "non-matching-file-id"
  49. nonMatchingContents = "non-matching-contents"
  50. // other.
  51. mySecret, token, password = "my-secret", "token", "password"
  52. one, two, three = "one", "two", "three"
  53. connectHost = "https://example.com"
  54. setupCheckFormat = "Setup: '%s', Check: '%s'"
  55. getSecretMapErrFormat = "%s: onepassword.GetSecretMap(...): -expected, +got:\n-%#v\n+%#v\n"
  56. getSecretErrFormat = "%s: onepassword.GetSecret(...): -expected, +got:\n-%#v\n+%#v\n"
  57. getAllSecretsErrFormat = "%s: onepassword.GetAllSecrets(...): -expected, +got:\n-%#v\n+%#v\n"
  58. validateStoreErrFormat = "%s: onepassword.validateStore(...): -expected, +got:\n-%#v\n+%#v\n"
  59. findItemErrFormat = "%s: onepassword.findItem(...): -expected, +got:\n-%#v\n+%#v\n"
  60. )
  61. func TestFindItem(t *testing.T) {
  62. type check struct {
  63. checkNote string
  64. findItemName string
  65. expectedItem *onepassword.Item
  66. expectedErr error
  67. }
  68. type testCase struct {
  69. setupNote string
  70. provider *ProviderOnePassword
  71. checks []check
  72. }
  73. testCases := []testCase{
  74. {
  75. setupNote: "valid basic: one vault, one item, one field",
  76. provider: &ProviderOnePassword{
  77. vaults: map[string]int{myVault: 1},
  78. client: fake.NewMockClient().
  79. AddPredictableVault(myVault).
  80. AddPredictableItemWithField(myVault, myItem, key1, value1),
  81. },
  82. checks: []check{
  83. {
  84. checkNote: "pass",
  85. findItemName: myItem,
  86. expectedErr: nil,
  87. expectedItem: &onepassword.Item{
  88. ID: myItemID,
  89. Title: myItem,
  90. Vault: onepassword.ItemVault{ID: myVaultID},
  91. Fields: []*onepassword.ItemField{
  92. {
  93. Label: key1,
  94. Value: value1,
  95. },
  96. },
  97. },
  98. },
  99. },
  100. },
  101. {
  102. setupNote: "multiple vaults, multiple items",
  103. provider: &ProviderOnePassword{
  104. vaults: map[string]int{myVault: 1, mySharedVault: 2},
  105. client: fake.NewMockClient().
  106. AddPredictableVault(myVault).
  107. AddPredictableItemWithField(myVault, myItem, key1, value1).
  108. AddPredictableVault(mySharedVault).
  109. AddPredictableItemWithField(mySharedVault, mySharedItem, sharedKey1, sharedValue1),
  110. },
  111. checks: []check{
  112. {
  113. checkNote: "can still get myItem",
  114. findItemName: myItem,
  115. expectedErr: nil,
  116. expectedItem: &onepassword.Item{
  117. ID: myItemID,
  118. Title: myItem,
  119. Vault: onepassword.ItemVault{ID: myVaultID},
  120. Fields: []*onepassword.ItemField{
  121. {
  122. Label: key1,
  123. Value: value1,
  124. },
  125. },
  126. },
  127. },
  128. {
  129. checkNote: "can also get mySharedItem",
  130. findItemName: mySharedItem,
  131. expectedErr: nil,
  132. expectedItem: &onepassword.Item{
  133. ID: mySharedItemID,
  134. Title: mySharedItem,
  135. Vault: onepassword.ItemVault{ID: mySharedVaultID},
  136. Fields: []*onepassword.ItemField{
  137. {
  138. Label: sharedKey1,
  139. Value: sharedValue1,
  140. },
  141. },
  142. },
  143. },
  144. },
  145. },
  146. {
  147. setupNote: "multiple vault matches when should be one",
  148. provider: &ProviderOnePassword{
  149. vaults: map[string]int{myVault: 1, mySharedVault: 2},
  150. client: fake.NewMockClient().
  151. AppendVault(myVault, onepassword.Vault{
  152. ID: myVaultID,
  153. Name: myVault,
  154. }).
  155. AppendVault(myVault, onepassword.Vault{
  156. ID: "my-vault-extra-match-id",
  157. Name: "my-vault-extra-match",
  158. }),
  159. },
  160. checks: []check{
  161. {
  162. checkNote: "two vaults",
  163. findItemName: myItem,
  164. expectedErr: fmt.Errorf("key not found in 1Password Vaults: my-item in: map[my-shared-vault:2 my-vault:1]"),
  165. },
  166. },
  167. },
  168. {
  169. setupNote: "no item matches when should be one",
  170. provider: &ProviderOnePassword{
  171. vaults: map[string]int{myVault: 1},
  172. client: fake.NewMockClient().
  173. AddPredictableVault(myVault),
  174. },
  175. checks: []check{
  176. {
  177. checkNote: "no exist",
  178. findItemName: "my-item-no-exist",
  179. expectedErr: fmt.Errorf(errKeyNotFound, fmt.Errorf("my-item-no-exist in: map[my-vault:1]")),
  180. },
  181. },
  182. },
  183. {
  184. setupNote: "multiple item matches when should be one",
  185. provider: &ProviderOnePassword{
  186. vaults: map[string]int{myVault: 1},
  187. client: fake.NewMockClient().
  188. AddPredictableVault(myVault).
  189. AddPredictableItemWithField(myVault, myItem, key1, value1).
  190. AppendItem(myVaultID, onepassword.Item{
  191. ID: "asdf",
  192. Title: myItem,
  193. Vault: onepassword.ItemVault{ID: myVaultID},
  194. }),
  195. },
  196. checks: []check{
  197. {
  198. checkNote: "multiple match",
  199. findItemName: myItem,
  200. expectedErr: fmt.Errorf(errExpectedOneItem, fmt.Errorf("'my-item', got 2")),
  201. },
  202. },
  203. },
  204. {
  205. setupNote: "ordered vaults",
  206. provider: &ProviderOnePassword{
  207. vaults: map[string]int{myVault: 1, mySharedVault: 2, myOtherVault: 3},
  208. client: fake.NewMockClient().
  209. AddPredictableVault(myVault).
  210. AddPredictableVault(mySharedVault).
  211. AddPredictableVault(myOtherVault).
  212. // // my-item
  213. // returned: my-item in my-vault
  214. AddPredictableItemWithField(myVault, myItem, key1, value1).
  215. // preempted: my-item in my-shared-vault
  216. AppendItem(mySharedVaultID, onepassword.Item{
  217. ID: myItemID,
  218. Title: myItem,
  219. Vault: onepassword.ItemVault{ID: mySharedVaultID},
  220. }).
  221. AppendItemField(mySharedVaultID, myItemID, onepassword.ItemField{
  222. Label: key1,
  223. Value: "value1-from-my-shared-vault",
  224. }).
  225. // preempted: my-item in my-other-vault
  226. AppendItem(myOtherVaultID, onepassword.Item{
  227. ID: myItemID,
  228. Title: myItem,
  229. Vault: onepassword.ItemVault{ID: myOtherVaultID},
  230. }).
  231. AppendItemField(myOtherVaultID, myItemID, onepassword.ItemField{
  232. Label: key1,
  233. Value: "value1-from-my-other-vault",
  234. }).
  235. // // my-shared-item
  236. // returned: my-shared-item in my-shared-vault
  237. AddPredictableItemWithField(mySharedVault, mySharedItem, sharedKey1, "sharedvalue1-from-my-shared-vault").
  238. // preempted: my-shared-item in my-other-vault
  239. AppendItem(myOtherVaultID, onepassword.Item{
  240. ID: mySharedItemID,
  241. Title: mySharedItem,
  242. Vault: onepassword.ItemVault{ID: myOtherVaultID},
  243. }).
  244. AppendItemField(myOtherVaultID, mySharedItemID, onepassword.ItemField{
  245. Label: sharedKey1,
  246. Value: "sharedvalue1-from-my-other-vault",
  247. }).
  248. // // my-other-item
  249. // returned: my-other-item in my-other-vault
  250. AddPredictableItemWithField(myOtherVault, myOtherItem, otherKey1, "othervalue1-from-my-other-vault"),
  251. },
  252. checks: []check{
  253. {
  254. // my-item in all three vaults, gets the one from my-vault
  255. checkNote: "gets item from my-vault",
  256. findItemName: myItem,
  257. expectedErr: nil,
  258. expectedItem: &onepassword.Item{
  259. ID: myItemID,
  260. Title: myItem,
  261. Vault: onepassword.ItemVault{ID: myVaultID},
  262. Fields: []*onepassword.ItemField{
  263. {
  264. Label: key1,
  265. Value: value1,
  266. },
  267. },
  268. },
  269. },
  270. {
  271. // my-shared-item in my-shared-vault and my-other-vault, gets the one from my-shared-vault
  272. checkNote: "gets item from my-shared-vault",
  273. findItemName: mySharedItem,
  274. expectedErr: nil,
  275. expectedItem: &onepassword.Item{
  276. ID: mySharedItemID,
  277. Title: mySharedItem,
  278. Vault: onepassword.ItemVault{ID: mySharedVaultID},
  279. Fields: []*onepassword.ItemField{
  280. {
  281. Label: sharedKey1,
  282. Value: "sharedvalue1-from-my-shared-vault",
  283. },
  284. },
  285. },
  286. },
  287. {
  288. // my-other-item in my-other-vault
  289. checkNote: "gets item from my-other-vault",
  290. findItemName: myOtherItem,
  291. expectedErr: nil,
  292. expectedItem: &onepassword.Item{
  293. ID: myOtherItemID,
  294. Title: myOtherItem,
  295. Vault: onepassword.ItemVault{ID: myOtherVaultID},
  296. Fields: []*onepassword.ItemField{
  297. {
  298. Label: otherKey1,
  299. Value: "othervalue1-from-my-other-vault",
  300. },
  301. },
  302. },
  303. },
  304. },
  305. },
  306. }
  307. // run the tests
  308. for _, tc := range testCases {
  309. for _, check := range tc.checks {
  310. got, err := tc.provider.findItem(check.findItemName)
  311. notes := fmt.Sprintf(setupCheckFormat, tc.setupNote, check.checkNote)
  312. if check.expectedErr == nil && err != nil {
  313. // expected no error, got one
  314. t.Errorf(findItemErrFormat, notes, nil, err)
  315. }
  316. if check.expectedErr != nil && err == nil {
  317. // expected an error, didn't get one
  318. t.Errorf(findItemErrFormat, notes, check.expectedErr.Error(), nil)
  319. }
  320. if check.expectedErr != nil && err != nil && err.Error() != check.expectedErr.Error() {
  321. // expected an error, got the wrong one
  322. t.Errorf(findItemErrFormat, notes, check.expectedErr.Error(), err.Error())
  323. }
  324. if check.expectedItem != nil {
  325. if !reflect.DeepEqual(check.expectedItem, got) {
  326. // expected a predefined item, got something else
  327. t.Errorf(findItemErrFormat, notes, check.expectedItem, got)
  328. }
  329. }
  330. }
  331. }
  332. }
  333. func TestValidateStore(t *testing.T) {
  334. type testCase struct {
  335. checkNote string
  336. store *esv1beta1.SecretStore
  337. clusterStore *esv1beta1.ClusterSecretStore
  338. expectedErr error
  339. }
  340. testCases := []testCase{
  341. {
  342. checkNote: "invalid: nil provider",
  343. store: &esv1beta1.SecretStore{
  344. TypeMeta: metav1.TypeMeta{
  345. Kind: "SecretStore",
  346. },
  347. Spec: esv1beta1.SecretStoreSpec{
  348. Provider: nil,
  349. },
  350. },
  351. expectedErr: fmt.Errorf(errOnePasswordStore, fmt.Errorf(errOnePasswordStoreNilSpecProvider)),
  352. },
  353. {
  354. checkNote: "invalid: nil OnePassword provider spec",
  355. store: &esv1beta1.SecretStore{
  356. TypeMeta: metav1.TypeMeta{
  357. Kind: "SecretStore",
  358. },
  359. Spec: esv1beta1.SecretStoreSpec{
  360. Provider: &esv1beta1.SecretStoreProvider{
  361. OnePassword: nil,
  362. },
  363. },
  364. },
  365. expectedErr: fmt.Errorf(errOnePasswordStore, fmt.Errorf(errOnePasswordStoreNilSpecProviderOnePassword)),
  366. },
  367. {
  368. checkNote: "valid secretStore",
  369. store: &esv1beta1.SecretStore{
  370. TypeMeta: metav1.TypeMeta{
  371. Kind: "SecretStore",
  372. },
  373. Spec: esv1beta1.SecretStoreSpec{
  374. Provider: &esv1beta1.SecretStoreProvider{
  375. OnePassword: &esv1beta1.OnePasswordProvider{
  376. Auth: &esv1beta1.OnePasswordAuth{
  377. SecretRef: &esv1beta1.OnePasswordAuthSecretRef{
  378. ConnectToken: esmeta.SecretKeySelector{
  379. Name: mySecret,
  380. Key: token,
  381. },
  382. },
  383. },
  384. ConnectHost: connectHost,
  385. Vaults: map[string]int{
  386. myVault: 1,
  387. },
  388. },
  389. },
  390. },
  391. },
  392. expectedErr: nil,
  393. },
  394. {
  395. checkNote: "invalid: illegal namespace on SecretStore",
  396. store: &esv1beta1.SecretStore{
  397. TypeMeta: metav1.TypeMeta{
  398. Kind: "SecretStore",
  399. },
  400. Spec: esv1beta1.SecretStoreSpec{
  401. Provider: &esv1beta1.SecretStoreProvider{
  402. OnePassword: &esv1beta1.OnePasswordProvider{
  403. Auth: &esv1beta1.OnePasswordAuth{
  404. SecretRef: &esv1beta1.OnePasswordAuthSecretRef{
  405. ConnectToken: esmeta.SecretKeySelector{
  406. Name: mySecret,
  407. Namespace: pointer.String("my-namespace"),
  408. Key: token,
  409. },
  410. },
  411. },
  412. ConnectHost: connectHost,
  413. Vaults: map[string]int{
  414. myVault: 1,
  415. myOtherVault: 2,
  416. },
  417. },
  418. },
  419. },
  420. },
  421. expectedErr: fmt.Errorf(errOnePasswordStore, fmt.Errorf("namespace not allowed with namespaced SecretStore")),
  422. },
  423. {
  424. checkNote: "invalid: more than one vault with the same number",
  425. store: &esv1beta1.SecretStore{
  426. TypeMeta: metav1.TypeMeta{
  427. Kind: "SecretStore",
  428. },
  429. Spec: esv1beta1.SecretStoreSpec{
  430. Provider: &esv1beta1.SecretStoreProvider{
  431. OnePassword: &esv1beta1.OnePasswordProvider{
  432. Auth: &esv1beta1.OnePasswordAuth{
  433. SecretRef: &esv1beta1.OnePasswordAuthSecretRef{
  434. ConnectToken: esmeta.SecretKeySelector{
  435. Name: mySecret,
  436. Key: token,
  437. },
  438. },
  439. },
  440. ConnectHost: connectHost,
  441. Vaults: map[string]int{
  442. myVault: 1,
  443. myOtherVault: 1,
  444. },
  445. },
  446. },
  447. },
  448. },
  449. expectedErr: fmt.Errorf(errOnePasswordStore, fmt.Errorf(errOnePasswordStoreNonUniqueVaultNumbers)),
  450. },
  451. {
  452. checkNote: "valid: clusterSecretStore",
  453. clusterStore: &esv1beta1.ClusterSecretStore{
  454. TypeMeta: metav1.TypeMeta{
  455. Kind: "ClusterSecretStore",
  456. },
  457. Spec: esv1beta1.SecretStoreSpec{
  458. Provider: &esv1beta1.SecretStoreProvider{
  459. OnePassword: &esv1beta1.OnePasswordProvider{
  460. Auth: &esv1beta1.OnePasswordAuth{
  461. SecretRef: &esv1beta1.OnePasswordAuthSecretRef{
  462. ConnectToken: esmeta.SecretKeySelector{
  463. Name: mySecret,
  464. Namespace: pointer.String("my-namespace"),
  465. Key: token,
  466. },
  467. },
  468. },
  469. ConnectHost: connectHost,
  470. Vaults: map[string]int{
  471. myVault: 1,
  472. },
  473. },
  474. },
  475. },
  476. },
  477. expectedErr: nil,
  478. },
  479. {
  480. checkNote: "invalid: clusterSecretStore without namespace",
  481. clusterStore: &esv1beta1.ClusterSecretStore{
  482. TypeMeta: metav1.TypeMeta{
  483. Kind: "ClusterSecretStore",
  484. },
  485. Spec: esv1beta1.SecretStoreSpec{
  486. Provider: &esv1beta1.SecretStoreProvider{
  487. OnePassword: &esv1beta1.OnePasswordProvider{
  488. Auth: &esv1beta1.OnePasswordAuth{
  489. SecretRef: &esv1beta1.OnePasswordAuthSecretRef{
  490. ConnectToken: esmeta.SecretKeySelector{
  491. Name: mySecret,
  492. Key: token,
  493. },
  494. },
  495. },
  496. ConnectHost: connectHost,
  497. Vaults: map[string]int{
  498. myVault: 1,
  499. myOtherVault: 2,
  500. },
  501. },
  502. },
  503. },
  504. },
  505. expectedErr: fmt.Errorf(errOnePasswordStore, fmt.Errorf("cluster scope requires namespace")),
  506. },
  507. {
  508. checkNote: "invalid: missing connectTokenSecretRef.name",
  509. store: &esv1beta1.SecretStore{
  510. TypeMeta: metav1.TypeMeta{
  511. Kind: "SecretStore",
  512. },
  513. Spec: esv1beta1.SecretStoreSpec{
  514. Provider: &esv1beta1.SecretStoreProvider{
  515. OnePassword: &esv1beta1.OnePasswordProvider{
  516. Auth: &esv1beta1.OnePasswordAuth{
  517. SecretRef: &esv1beta1.OnePasswordAuthSecretRef{
  518. ConnectToken: esmeta.SecretKeySelector{
  519. Key: token,
  520. },
  521. },
  522. },
  523. ConnectHost: connectHost,
  524. Vaults: map[string]int{
  525. myVault: 1,
  526. myOtherVault: 2,
  527. },
  528. },
  529. },
  530. },
  531. },
  532. expectedErr: fmt.Errorf(errOnePasswordStore, fmt.Errorf(errOnePasswordStoreMissingRefName)),
  533. },
  534. {
  535. checkNote: "invalid: missing connectTokenSecretRef.key",
  536. store: &esv1beta1.SecretStore{
  537. TypeMeta: metav1.TypeMeta{
  538. Kind: "SecretStore",
  539. },
  540. Spec: esv1beta1.SecretStoreSpec{
  541. Provider: &esv1beta1.SecretStoreProvider{
  542. OnePassword: &esv1beta1.OnePasswordProvider{
  543. Auth: &esv1beta1.OnePasswordAuth{
  544. SecretRef: &esv1beta1.OnePasswordAuthSecretRef{
  545. ConnectToken: esmeta.SecretKeySelector{
  546. Name: mySecret,
  547. },
  548. },
  549. },
  550. ConnectHost: connectHost,
  551. Vaults: map[string]int{
  552. myVault: 1,
  553. myOtherVault: 2,
  554. },
  555. },
  556. },
  557. },
  558. },
  559. expectedErr: fmt.Errorf(errOnePasswordStore, fmt.Errorf(errOnePasswordStoreMissingRefKey)),
  560. },
  561. {
  562. checkNote: "invalid: at least one vault",
  563. store: &esv1beta1.SecretStore{
  564. TypeMeta: metav1.TypeMeta{
  565. Kind: "SecretStore",
  566. },
  567. Spec: esv1beta1.SecretStoreSpec{
  568. Provider: &esv1beta1.SecretStoreProvider{
  569. OnePassword: &esv1beta1.OnePasswordProvider{
  570. Auth: &esv1beta1.OnePasswordAuth{
  571. SecretRef: &esv1beta1.OnePasswordAuthSecretRef{
  572. ConnectToken: esmeta.SecretKeySelector{
  573. Name: mySecret,
  574. Key: token,
  575. },
  576. },
  577. },
  578. ConnectHost: connectHost,
  579. Vaults: map[string]int{},
  580. },
  581. },
  582. },
  583. },
  584. expectedErr: fmt.Errorf(errOnePasswordStore, fmt.Errorf(errOnePasswordStoreAtLeastOneVault)),
  585. },
  586. {
  587. checkNote: "invalid: url",
  588. store: &esv1beta1.SecretStore{
  589. TypeMeta: metav1.TypeMeta{
  590. Kind: "SecretStore",
  591. },
  592. Spec: esv1beta1.SecretStoreSpec{
  593. Provider: &esv1beta1.SecretStoreProvider{
  594. OnePassword: &esv1beta1.OnePasswordProvider{
  595. Auth: &esv1beta1.OnePasswordAuth{
  596. SecretRef: &esv1beta1.OnePasswordAuthSecretRef{
  597. ConnectToken: esmeta.SecretKeySelector{
  598. Name: mySecret,
  599. Key: token,
  600. },
  601. },
  602. },
  603. ConnectHost: ":/invalid.invalid",
  604. Vaults: map[string]int{
  605. myVault: 1,
  606. },
  607. },
  608. },
  609. },
  610. },
  611. expectedErr: fmt.Errorf(errOnePasswordStore, fmt.Errorf(errOnePasswordStoreInvalidConnectHost, fmt.Errorf("parse \":/invalid.invalid\": missing protocol scheme"))),
  612. },
  613. }
  614. // run the tests
  615. for _, tc := range testCases {
  616. var err error
  617. if tc.store == nil {
  618. err = validateStore(tc.clusterStore)
  619. } else {
  620. err = validateStore(tc.store)
  621. }
  622. notes := fmt.Sprintf("Check: '%s'", tc.checkNote)
  623. if tc.expectedErr == nil && err != nil {
  624. // expected no error, got one
  625. t.Errorf(validateStoreErrFormat, notes, nil, err)
  626. }
  627. if tc.expectedErr != nil && err == nil {
  628. // expected an error, didn't get one
  629. t.Errorf(validateStoreErrFormat, notes, tc.expectedErr.Error(), nil)
  630. }
  631. if tc.expectedErr != nil && err != nil && err.Error() != tc.expectedErr.Error() {
  632. // expected an error, got the wrong one
  633. t.Errorf(validateStoreErrFormat, notes, tc.expectedErr.Error(), err.Error())
  634. }
  635. }
  636. }
  637. // most functionality is tested in TestFindItem
  638. //
  639. // here we just check that an empty Property defaults to "password",
  640. // files are loaded, and
  641. // the data or errors are properly returned
  642. func TestGetSecret(t *testing.T) {
  643. type check struct {
  644. checkNote string
  645. ref esv1beta1.ExternalSecretDataRemoteRef
  646. expectedValue string
  647. expectedErr error
  648. }
  649. type testCase struct {
  650. setupNote string
  651. provider *ProviderOnePassword
  652. checks []check
  653. }
  654. testCases := []testCase{
  655. {
  656. setupNote: "one vault, one item, two fields",
  657. provider: &ProviderOnePassword{
  658. vaults: map[string]int{myVault: 1},
  659. client: fake.NewMockClient().
  660. AddPredictableVault(myVault).
  661. AddPredictableItemWithField(myVault, myItem, key1, value1).
  662. AppendItemField(myVaultID, myItemID, onepassword.ItemField{
  663. Label: password,
  664. Value: value2,
  665. }),
  666. },
  667. checks: []check{
  668. {
  669. checkNote: key1,
  670. ref: esv1beta1.ExternalSecretDataRemoteRef{
  671. Key: myItem,
  672. Property: key1,
  673. },
  674. expectedValue: value1,
  675. expectedErr: nil,
  676. },
  677. {
  678. checkNote: "'password' (defaulted property)",
  679. ref: esv1beta1.ExternalSecretDataRemoteRef{
  680. Key: myItem,
  681. },
  682. expectedValue: value2,
  683. expectedErr: nil,
  684. },
  685. {
  686. checkNote: "'ref.version' not implemented",
  687. ref: esv1beta1.ExternalSecretDataRemoteRef{
  688. Key: myItem,
  689. Property: key1,
  690. Version: "123",
  691. },
  692. expectedErr: fmt.Errorf(errVersionNotImplemented),
  693. },
  694. },
  695. },
  696. {
  697. setupNote: "files are loaded",
  698. provider: &ProviderOnePassword{
  699. vaults: map[string]int{myVault: 1},
  700. client: fake.NewMockClient().
  701. AddPredictableVault(myVault).
  702. AppendItem(myVaultID, onepassword.Item{
  703. ID: myItemID,
  704. Title: myItem,
  705. Vault: onepassword.ItemVault{ID: myVaultID},
  706. Category: documentCategory,
  707. Files: []*onepassword.File{
  708. {
  709. ID: myFilePNGID,
  710. Name: myFilePNG,
  711. },
  712. },
  713. }).
  714. SetFileContents(myFilePNG, []byte(myContents)),
  715. },
  716. checks: []check{
  717. {
  718. checkNote: "file named my-file.png",
  719. ref: esv1beta1.ExternalSecretDataRemoteRef{
  720. Key: myItem,
  721. Property: myFilePNG,
  722. },
  723. expectedValue: myContents,
  724. expectedErr: nil,
  725. },
  726. {
  727. checkNote: "empty ref.Property",
  728. ref: esv1beta1.ExternalSecretDataRemoteRef{
  729. Key: myItem,
  730. },
  731. expectedValue: myContents,
  732. expectedErr: nil,
  733. },
  734. {
  735. checkNote: "file non existent",
  736. ref: esv1beta1.ExternalSecretDataRemoteRef{
  737. Key: myItem,
  738. Property: "you-cant-find-me.png",
  739. },
  740. expectedErr: fmt.Errorf(errDocumentNotFound, fmt.Errorf("'my-item', 'you-cant-find-me.png'")),
  741. },
  742. },
  743. },
  744. {
  745. setupNote: "one vault, one item, two fields w/ same Label",
  746. provider: &ProviderOnePassword{
  747. vaults: map[string]int{myVault: 1},
  748. client: fake.NewMockClient().
  749. AddPredictableVault(myVault).
  750. AddPredictableItemWithField(myVault, myItem, key1, value1).
  751. AppendItemField(myVaultID, myItemID, onepassword.ItemField{
  752. Label: key1,
  753. Value: value2,
  754. }),
  755. },
  756. checks: []check{
  757. {
  758. checkNote: key1,
  759. ref: esv1beta1.ExternalSecretDataRemoteRef{
  760. Key: myItem,
  761. Property: key1,
  762. },
  763. expectedErr: fmt.Errorf(errExpectedOneField, fmt.Errorf("'key1' in 'my-item', got 2")),
  764. },
  765. },
  766. },
  767. }
  768. // run the tests
  769. for _, tc := range testCases {
  770. for _, check := range tc.checks {
  771. got, err := tc.provider.GetSecret(context.Background(), check.ref)
  772. notes := fmt.Sprintf(setupCheckFormat, tc.setupNote, check.checkNote)
  773. if check.expectedErr == nil && err != nil {
  774. // expected no error, got one
  775. t.Errorf(getSecretErrFormat, notes, nil, err)
  776. }
  777. if check.expectedErr != nil && err == nil {
  778. // expected an error, didn't get one
  779. t.Errorf(getSecretErrFormat, notes, check.expectedErr.Error(), nil)
  780. }
  781. if check.expectedErr != nil && err != nil && err.Error() != check.expectedErr.Error() {
  782. // expected an error, got the wrong one
  783. t.Errorf(getSecretErrFormat, notes, check.expectedErr.Error(), err.Error())
  784. }
  785. if check.expectedValue != "" {
  786. if check.expectedValue != string(got) {
  787. // expected a predefined value, got something else
  788. t.Errorf(getSecretErrFormat, notes, check.expectedValue, string(got))
  789. }
  790. }
  791. }
  792. }
  793. }
  794. // most functionality is tested in TestFindItem. here we just check:
  795. //
  796. // all keys are fetched and the map is compiled correctly,
  797. // files are loaded, and the data or errors are properly returned.
  798. func TestGetSecretMap(t *testing.T) {
  799. type check struct {
  800. checkNote string
  801. ref esv1beta1.ExternalSecretDataRemoteRef
  802. expectedMap map[string][]byte
  803. expectedErr error
  804. }
  805. type testCase struct {
  806. setupNote string
  807. provider *ProviderOnePassword
  808. checks []check
  809. }
  810. testCases := []testCase{
  811. {
  812. setupNote: "one vault, one item, two fields",
  813. provider: &ProviderOnePassword{
  814. vaults: map[string]int{myVault: 1},
  815. client: fake.NewMockClient().
  816. AddPredictableVault(myVault).
  817. AddPredictableItemWithField(myVault, myItem, key1, value1).
  818. AppendItemField(myVaultID, myItemID, onepassword.ItemField{
  819. Label: password,
  820. Value: value2,
  821. }),
  822. },
  823. checks: []check{
  824. {
  825. checkNote: "all Properties",
  826. ref: esv1beta1.ExternalSecretDataRemoteRef{
  827. Key: myItem,
  828. },
  829. expectedMap: map[string][]byte{
  830. key1: []byte(value1),
  831. password: []byte(value2),
  832. },
  833. expectedErr: nil,
  834. },
  835. {
  836. checkNote: "limit by Property",
  837. ref: esv1beta1.ExternalSecretDataRemoteRef{
  838. Key: myItem,
  839. Property: password,
  840. },
  841. expectedMap: map[string][]byte{
  842. password: []byte(value2),
  843. },
  844. expectedErr: nil,
  845. },
  846. {
  847. checkNote: "'ref.version' not implemented",
  848. ref: esv1beta1.ExternalSecretDataRemoteRef{
  849. Key: myItem,
  850. Property: key1,
  851. Version: "123",
  852. },
  853. expectedErr: fmt.Errorf(errVersionNotImplemented),
  854. },
  855. },
  856. },
  857. {
  858. setupNote: "files",
  859. provider: &ProviderOnePassword{
  860. vaults: map[string]int{myVault: 1},
  861. client: fake.NewMockClient().
  862. AddPredictableVault(myVault).
  863. AppendItem(myVaultID, onepassword.Item{
  864. ID: myItemID,
  865. Title: myItem,
  866. Vault: onepassword.ItemVault{ID: myVaultID},
  867. Category: documentCategory,
  868. Files: []*onepassword.File{
  869. {
  870. ID: myFilePNGID,
  871. Name: myFilePNG,
  872. },
  873. {
  874. ID: myFile2ID,
  875. Name: myFile2PNG,
  876. },
  877. },
  878. }).
  879. SetFileContents(myFilePNG, []byte(myContents)).
  880. SetFileContents(myFile2PNG, []byte(myContents2)),
  881. },
  882. checks: []check{
  883. {
  884. checkNote: "all Properties",
  885. ref: esv1beta1.ExternalSecretDataRemoteRef{
  886. Key: myItem,
  887. },
  888. expectedMap: map[string][]byte{
  889. myFilePNG: []byte(myContents),
  890. myFile2PNG: []byte(myContents2),
  891. },
  892. expectedErr: nil,
  893. },
  894. {
  895. checkNote: "limit by Property",
  896. ref: esv1beta1.ExternalSecretDataRemoteRef{
  897. Key: myItem,
  898. Property: myFilePNG,
  899. },
  900. expectedMap: map[string][]byte{
  901. myFilePNG: []byte(myContents),
  902. },
  903. expectedErr: nil,
  904. },
  905. },
  906. },
  907. {
  908. setupNote: "one vault, one item, two fields w/ same Label",
  909. provider: &ProviderOnePassword{
  910. vaults: map[string]int{myVault: 1},
  911. client: fake.NewMockClient().
  912. AddPredictableVault(myVault).
  913. AddPredictableItemWithField(myVault, myItem, key1, value1).
  914. AppendItemField(myVaultID, myItemID, onepassword.ItemField{
  915. Label: key1,
  916. Value: value2,
  917. }),
  918. },
  919. checks: []check{
  920. {
  921. checkNote: key1,
  922. ref: esv1beta1.ExternalSecretDataRemoteRef{
  923. Key: myItem,
  924. },
  925. expectedMap: nil,
  926. expectedErr: fmt.Errorf(errExpectedOneField, fmt.Errorf("'key1' in 'my-item', got 2")),
  927. },
  928. },
  929. },
  930. }
  931. // run the tests
  932. for _, tc := range testCases {
  933. for _, check := range tc.checks {
  934. gotMap, err := tc.provider.GetSecretMap(context.Background(), check.ref)
  935. notes := fmt.Sprintf(setupCheckFormat, tc.setupNote, check.checkNote)
  936. if check.expectedErr == nil && err != nil {
  937. // expected no error, got one
  938. t.Errorf(getSecretMapErrFormat, notes, nil, err)
  939. }
  940. if check.expectedErr != nil && err == nil {
  941. // expected an error, didn't get one
  942. t.Errorf(getSecretMapErrFormat, notes, check.expectedErr.Error(), nil)
  943. }
  944. if check.expectedErr != nil && err != nil && err.Error() != check.expectedErr.Error() {
  945. // expected an error, got the wrong one
  946. t.Errorf(getSecretMapErrFormat, notes, check.expectedErr.Error(), err.Error())
  947. }
  948. if !reflect.DeepEqual(check.expectedMap, gotMap) {
  949. // expected a predefined map, got something else
  950. t.Errorf(getSecretMapErrFormat, notes, check.expectedMap, gotMap)
  951. }
  952. }
  953. }
  954. }
  955. func TestGetAllSecrets(t *testing.T) {
  956. type check struct {
  957. checkNote string
  958. ref esv1beta1.ExternalSecretFind
  959. expectedMap map[string][]byte
  960. expectedErr error
  961. }
  962. type testCase struct {
  963. setupNote string
  964. provider *ProviderOnePassword
  965. checks []check
  966. }
  967. testCases := []testCase{
  968. {
  969. setupNote: "three vaults, three items, all different field Labels",
  970. provider: &ProviderOnePassword{
  971. vaults: map[string]int{myVault: 1, myOtherVault: 2, myNonMatchingVault: 3},
  972. client: fake.NewMockClient().
  973. AddPredictableVault(myVault).
  974. AddPredictableItemWithField(myVault, myItem, key1, value1).
  975. AppendItemField(myVaultID, myItemID, onepassword.ItemField{
  976. Label: key2,
  977. Value: value2,
  978. }).
  979. AddPredictableVault(myOtherVault).
  980. AddPredictableItemWithField(myOtherVault, myOtherItem, key3, value3).
  981. AppendItemField(myOtherVaultID, myOtherItemID, onepassword.ItemField{
  982. Label: key4,
  983. Value: value4,
  984. }).
  985. AddPredictableVault(myNonMatchingVault).
  986. AddPredictableItemWithField(myNonMatchingVault, myNonMatchingItem, "non-matching5", "value5").
  987. AppendItemField(myNonMatchingVaultID, myNonMatchingItemID, onepassword.ItemField{
  988. Label: "non-matching6",
  989. Value: "value6",
  990. }),
  991. },
  992. checks: []check{
  993. {
  994. checkNote: "find some with path only",
  995. ref: esv1beta1.ExternalSecretFind{
  996. Path: pointer.String(myItem),
  997. },
  998. expectedMap: map[string][]byte{
  999. key1: []byte(value1),
  1000. key2: []byte(value2),
  1001. },
  1002. expectedErr: nil,
  1003. },
  1004. {
  1005. checkNote: "find most with regex 'key*'",
  1006. ref: esv1beta1.ExternalSecretFind{
  1007. Name: &esv1beta1.FindName{
  1008. RegExp: "key*",
  1009. },
  1010. },
  1011. expectedMap: map[string][]byte{
  1012. key1: []byte(value1),
  1013. key2: []byte(value2),
  1014. key3: []byte(value3),
  1015. key4: []byte(value4),
  1016. },
  1017. expectedErr: nil,
  1018. },
  1019. {
  1020. checkNote: "find some with regex 'key*' and path 'my-other-item'",
  1021. ref: esv1beta1.ExternalSecretFind{
  1022. Name: &esv1beta1.FindName{
  1023. RegExp: "key*",
  1024. },
  1025. Path: pointer.String(myOtherItem),
  1026. },
  1027. expectedMap: map[string][]byte{
  1028. key3: []byte(value3),
  1029. key4: []byte(value4),
  1030. },
  1031. expectedErr: nil,
  1032. },
  1033. {
  1034. checkNote: "find none with regex 'asdf*'",
  1035. ref: esv1beta1.ExternalSecretFind{
  1036. Name: &esv1beta1.FindName{
  1037. RegExp: "asdf*",
  1038. },
  1039. },
  1040. expectedMap: map[string][]byte{},
  1041. expectedErr: nil,
  1042. },
  1043. {
  1044. checkNote: "find none with path 'no-exist'",
  1045. ref: esv1beta1.ExternalSecretFind{
  1046. Name: &esv1beta1.FindName{
  1047. RegExp: "key*",
  1048. },
  1049. Path: pointer.String("no-exist"),
  1050. },
  1051. expectedMap: map[string][]byte{},
  1052. expectedErr: nil,
  1053. },
  1054. {
  1055. checkNote: "error when find.tags",
  1056. ref: esv1beta1.ExternalSecretFind{
  1057. Name: &esv1beta1.FindName{
  1058. RegExp: "key*",
  1059. },
  1060. Tags: map[string]string{
  1061. "asdf": "fdas",
  1062. },
  1063. },
  1064. expectedErr: fmt.Errorf(errTagsNotImplemented),
  1065. },
  1066. },
  1067. },
  1068. {
  1069. setupNote: "3 vaults, 4 items, 5 files",
  1070. provider: &ProviderOnePassword{
  1071. vaults: map[string]int{myVault: 1, myOtherVault: 2, myNonMatchingVault: 3},
  1072. client: fake.NewMockClient().
  1073. // my-vault
  1074. AddPredictableVault(myVault).
  1075. AppendItem(myVaultID, onepassword.Item{
  1076. ID: myItemID,
  1077. Title: myItem,
  1078. Vault: onepassword.ItemVault{ID: myVaultID},
  1079. Category: documentCategory,
  1080. Files: []*onepassword.File{
  1081. {
  1082. ID: myFilePNGID,
  1083. Name: myFilePNG,
  1084. },
  1085. {
  1086. ID: mySecondFileTXTID,
  1087. Name: mySecondFileTXT,
  1088. },
  1089. },
  1090. }).
  1091. SetFileContents(myFilePNG, []byte(myContents)).
  1092. SetFileContents(mySecondFileTXT, []byte(mySecondContents)).
  1093. AppendItem(myVaultID, onepassword.Item{
  1094. ID: "my-item-2-id",
  1095. Title: "my-item-2",
  1096. Vault: onepassword.ItemVault{ID: myVaultID},
  1097. Category: documentCategory,
  1098. Files: []*onepassword.File{
  1099. {
  1100. ID: myFile2ID,
  1101. Name: myFile2TXT,
  1102. },
  1103. },
  1104. }).
  1105. SetFileContents(myFile2TXT, []byte(myContents2)).
  1106. // my-other-vault
  1107. AddPredictableVault(myOtherVault).
  1108. AppendItem(myOtherVaultID, onepassword.Item{
  1109. ID: myOtherItemID,
  1110. Title: myOtherItem,
  1111. Vault: onepassword.ItemVault{ID: myOtherVaultID},
  1112. Category: documentCategory,
  1113. Files: []*onepassword.File{
  1114. {
  1115. ID: myOtherFilePNGID,
  1116. Name: myOtherFilePNG,
  1117. },
  1118. },
  1119. }).
  1120. SetFileContents(myOtherFilePNG, []byte(myOtherContents)).
  1121. // my-non-matching-vault
  1122. AddPredictableVault(myNonMatchingVault).
  1123. AppendItem(myNonMatchingVaultID, onepassword.Item{
  1124. ID: myNonMatchingItemID,
  1125. Title: myNonMatchingItem,
  1126. Vault: onepassword.ItemVault{ID: myNonMatchingVaultID},
  1127. Category: documentCategory,
  1128. Files: []*onepassword.File{
  1129. {
  1130. ID: nonMatchingFilePNGID,
  1131. Name: nonMatchingFilePNG,
  1132. },
  1133. },
  1134. }).
  1135. SetFileContents(nonMatchingFilePNG, []byte(nonMatchingContents)),
  1136. },
  1137. checks: []check{
  1138. {
  1139. checkNote: "find most with regex '^my-*'",
  1140. ref: esv1beta1.ExternalSecretFind{
  1141. Name: &esv1beta1.FindName{
  1142. RegExp: "^my-*",
  1143. },
  1144. },
  1145. expectedMap: map[string][]byte{
  1146. myFilePNG: []byte(myContents),
  1147. mySecondFileTXT: []byte(mySecondContents),
  1148. myFile2TXT: []byte(myContents2),
  1149. myOtherFilePNG: []byte(myOtherContents),
  1150. },
  1151. expectedErr: nil,
  1152. },
  1153. {
  1154. checkNote: "find some with regex '^my-*' and path 'my-other-item'",
  1155. ref: esv1beta1.ExternalSecretFind{
  1156. Name: &esv1beta1.FindName{
  1157. RegExp: "^my-*",
  1158. },
  1159. Path: pointer.String(myOtherItem),
  1160. },
  1161. expectedMap: map[string][]byte{
  1162. myOtherFilePNG: []byte(myOtherContents),
  1163. },
  1164. expectedErr: nil,
  1165. },
  1166. {
  1167. checkNote: "find none with regex '^asdf*'",
  1168. ref: esv1beta1.ExternalSecretFind{
  1169. Name: &esv1beta1.FindName{
  1170. RegExp: "^asdf*",
  1171. },
  1172. },
  1173. expectedMap: map[string][]byte{},
  1174. expectedErr: nil,
  1175. },
  1176. {
  1177. checkNote: "find none with path 'no-exist'",
  1178. ref: esv1beta1.ExternalSecretFind{
  1179. Name: &esv1beta1.FindName{
  1180. RegExp: "^my-*",
  1181. },
  1182. Path: pointer.String("no-exist"),
  1183. },
  1184. expectedMap: map[string][]byte{},
  1185. expectedErr: nil,
  1186. },
  1187. },
  1188. },
  1189. {
  1190. setupNote: "two fields/files with same name, first one wins",
  1191. provider: &ProviderOnePassword{
  1192. vaults: map[string]int{myVault: 1, myOtherVault: 2},
  1193. client: fake.NewMockClient().
  1194. // my-vault
  1195. AddPredictableVault(myVault).
  1196. AddPredictableItemWithField(myVault, myItem, key1, value1).
  1197. AddPredictableItemWithField(myVault, "my-second-item", key1, "value-second").
  1198. AppendItem(myVaultID, onepassword.Item{
  1199. ID: "file-item-id",
  1200. Title: "file-item",
  1201. Vault: onepassword.ItemVault{ID: myVaultID},
  1202. Category: documentCategory,
  1203. Files: []*onepassword.File{
  1204. {
  1205. ID: filePNGID,
  1206. Name: filePNG,
  1207. },
  1208. },
  1209. }).
  1210. SetFileContents(filePNG, []byte(myContents)).
  1211. AppendItem(myVaultID, onepassword.Item{
  1212. ID: "file-item-2-id",
  1213. Title: "file-item-2",
  1214. Vault: onepassword.ItemVault{ID: myVaultID},
  1215. Category: documentCategory,
  1216. Files: []*onepassword.File{
  1217. {
  1218. ID: "file-2-id",
  1219. Name: filePNG,
  1220. },
  1221. },
  1222. }).
  1223. // my-other-vault
  1224. AddPredictableVault(myOtherVault).
  1225. AddPredictableItemWithField(myOtherVault, myOtherItem, key1, "value-other").
  1226. AppendItem(myOtherVaultID, onepassword.Item{
  1227. ID: "file-item-other-id",
  1228. Title: "file-item-other",
  1229. Vault: onepassword.ItemVault{ID: myOtherVaultID},
  1230. Category: documentCategory,
  1231. Files: []*onepassword.File{
  1232. {
  1233. ID: "other-file-id",
  1234. Name: filePNG,
  1235. },
  1236. },
  1237. }),
  1238. },
  1239. checks: []check{
  1240. {
  1241. checkNote: "find fields with regex '^key*'",
  1242. ref: esv1beta1.ExternalSecretFind{
  1243. Name: &esv1beta1.FindName{
  1244. RegExp: "^key*",
  1245. },
  1246. },
  1247. expectedMap: map[string][]byte{
  1248. key1: []byte(value1),
  1249. },
  1250. expectedErr: nil,
  1251. },
  1252. {
  1253. checkNote: "find files with regex '^file*item*'",
  1254. ref: esv1beta1.ExternalSecretFind{
  1255. Name: &esv1beta1.FindName{
  1256. RegExp: "^file*",
  1257. },
  1258. },
  1259. expectedMap: map[string][]byte{
  1260. filePNG: []byte(myContents),
  1261. },
  1262. expectedErr: nil,
  1263. },
  1264. },
  1265. },
  1266. }
  1267. // run the tests
  1268. for _, tc := range testCases {
  1269. for _, check := range tc.checks {
  1270. gotMap, err := tc.provider.GetAllSecrets(context.Background(), check.ref)
  1271. notes := fmt.Sprintf(setupCheckFormat, tc.setupNote, check.checkNote)
  1272. if check.expectedErr == nil && err != nil {
  1273. // expected no error, got one
  1274. t.Fatalf(getAllSecretsErrFormat, notes, nil, err)
  1275. }
  1276. if check.expectedErr != nil && err == nil {
  1277. // expected an error, didn't get one
  1278. t.Errorf(getAllSecretsErrFormat, notes, check.expectedErr.Error(), nil)
  1279. }
  1280. if check.expectedErr != nil && err != nil && err.Error() != check.expectedErr.Error() {
  1281. // expected an error, got the wrong one
  1282. t.Errorf(getAllSecretsErrFormat, notes, check.expectedErr.Error(), err.Error())
  1283. }
  1284. if !reflect.DeepEqual(check.expectedMap, gotMap) {
  1285. // expected a predefined map, got something else
  1286. t.Errorf(getAllSecretsErrFormat, notes, check.expectedMap, gotMap)
  1287. }
  1288. }
  1289. }
  1290. }
  1291. func TestSortVaults(t *testing.T) {
  1292. type testCase struct {
  1293. vaults map[string]int
  1294. expected []string
  1295. }
  1296. testCases := []testCase{
  1297. {
  1298. vaults: map[string]int{
  1299. one: 1,
  1300. three: 3,
  1301. two: 2,
  1302. },
  1303. expected: []string{
  1304. one,
  1305. two,
  1306. three,
  1307. },
  1308. },
  1309. {
  1310. vaults: map[string]int{
  1311. "four": 100,
  1312. one: 1,
  1313. three: 3,
  1314. two: 2,
  1315. },
  1316. expected: []string{
  1317. one,
  1318. two,
  1319. three,
  1320. "four",
  1321. },
  1322. },
  1323. }
  1324. // run the tests
  1325. for _, tc := range testCases {
  1326. got := sortVaults(tc.vaults)
  1327. if !reflect.DeepEqual(got, tc.expected) {
  1328. t.Errorf("onepassword.sortVaults(...): -expected, +got:\n-%#v\n+%#v\n", tc.expected, got)
  1329. }
  1330. }
  1331. }
  1332. func TestHasUniqueVaultNumbers(t *testing.T) {
  1333. type testCase struct {
  1334. vaults map[string]int
  1335. expected bool
  1336. }
  1337. testCases := []testCase{
  1338. {
  1339. vaults: map[string]int{
  1340. one: 1,
  1341. three: 3,
  1342. two: 2,
  1343. },
  1344. expected: true,
  1345. },
  1346. {
  1347. vaults: map[string]int{
  1348. "four": 100,
  1349. one: 1,
  1350. three: 3,
  1351. two: 2,
  1352. "eight": 100,
  1353. },
  1354. expected: false,
  1355. },
  1356. {
  1357. vaults: map[string]int{
  1358. one: 1,
  1359. "1": 1,
  1360. three: 3,
  1361. two: 2,
  1362. },
  1363. expected: false,
  1364. },
  1365. }
  1366. // run the tests
  1367. for _, tc := range testCases {
  1368. got := hasUniqueVaultNumbers(tc.vaults)
  1369. if got != tc.expected {
  1370. t.Errorf("onepassword.hasUniqueVaultNumbers(...): -expected, +got:\n-%#v\n+%#v\n", tc.expected, got)
  1371. }
  1372. }
  1373. }