onepassword_test.go 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407
  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.StringPtr("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.StringPtr("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. // here we just check that an empty Property defaults to "password",
  639. // files are loaded, and
  640. // the data or errors are properly returned
  641. func TestGetSecret(t *testing.T) {
  642. type check struct {
  643. checkNote string
  644. ref esv1beta1.ExternalSecretDataRemoteRef
  645. expectedValue string
  646. expectedErr error
  647. }
  648. type testCase struct {
  649. setupNote string
  650. provider *ProviderOnePassword
  651. checks []check
  652. }
  653. testCases := []testCase{
  654. {
  655. setupNote: "one vault, one item, two fields",
  656. provider: &ProviderOnePassword{
  657. vaults: map[string]int{myVault: 1},
  658. client: fake.NewMockClient().
  659. AddPredictableVault(myVault).
  660. AddPredictableItemWithField(myVault, myItem, key1, value1).
  661. AppendItemField(myVaultID, myItemID, onepassword.ItemField{
  662. Label: password,
  663. Value: value2,
  664. }),
  665. },
  666. checks: []check{
  667. {
  668. checkNote: key1,
  669. ref: esv1beta1.ExternalSecretDataRemoteRef{
  670. Key: myItem,
  671. Property: key1,
  672. },
  673. expectedValue: value1,
  674. expectedErr: nil,
  675. },
  676. {
  677. checkNote: "'password' (defaulted property)",
  678. ref: esv1beta1.ExternalSecretDataRemoteRef{
  679. Key: myItem,
  680. },
  681. expectedValue: value2,
  682. expectedErr: nil,
  683. },
  684. {
  685. checkNote: "'ref.version' not implemented",
  686. ref: esv1beta1.ExternalSecretDataRemoteRef{
  687. Key: myItem,
  688. Property: key1,
  689. Version: "123",
  690. },
  691. expectedErr: fmt.Errorf(errVersionNotImplemented),
  692. },
  693. },
  694. },
  695. {
  696. setupNote: "files are loaded",
  697. provider: &ProviderOnePassword{
  698. vaults: map[string]int{myVault: 1},
  699. client: fake.NewMockClient().
  700. AddPredictableVault(myVault).
  701. AppendItem(myVaultID, onepassword.Item{
  702. ID: myItemID,
  703. Title: myItem,
  704. Vault: onepassword.ItemVault{ID: myVaultID},
  705. Category: documentCategory,
  706. Files: []*onepassword.File{
  707. {
  708. ID: myFilePNGID,
  709. Name: myFilePNG,
  710. },
  711. },
  712. }).
  713. SetFileContents(myFilePNG, []byte(myContents)),
  714. },
  715. checks: []check{
  716. {
  717. checkNote: "file named my-file.png",
  718. ref: esv1beta1.ExternalSecretDataRemoteRef{
  719. Key: myItem,
  720. Property: myFilePNG,
  721. },
  722. expectedValue: myContents,
  723. expectedErr: nil,
  724. },
  725. {
  726. checkNote: "empty ref.Property",
  727. ref: esv1beta1.ExternalSecretDataRemoteRef{
  728. Key: myItem,
  729. },
  730. expectedValue: myContents,
  731. expectedErr: nil,
  732. },
  733. {
  734. checkNote: "file non existent",
  735. ref: esv1beta1.ExternalSecretDataRemoteRef{
  736. Key: myItem,
  737. Property: "you-cant-find-me.png",
  738. },
  739. expectedErr: fmt.Errorf(errDocumentNotFound, fmt.Errorf("'my-item', 'you-cant-find-me.png'")),
  740. },
  741. },
  742. },
  743. {
  744. setupNote: "one vault, one item, two fields w/ same Label",
  745. provider: &ProviderOnePassword{
  746. vaults: map[string]int{myVault: 1},
  747. client: fake.NewMockClient().
  748. AddPredictableVault(myVault).
  749. AddPredictableItemWithField(myVault, myItem, key1, value1).
  750. AppendItemField(myVaultID, myItemID, onepassword.ItemField{
  751. Label: key1,
  752. Value: value2,
  753. }),
  754. },
  755. checks: []check{
  756. {
  757. checkNote: key1,
  758. ref: esv1beta1.ExternalSecretDataRemoteRef{
  759. Key: myItem,
  760. Property: key1,
  761. },
  762. expectedErr: fmt.Errorf(errExpectedOneField, fmt.Errorf("'key1' in 'my-item', got 2")),
  763. },
  764. },
  765. },
  766. }
  767. // run the tests
  768. for _, tc := range testCases {
  769. for _, check := range tc.checks {
  770. got, err := tc.provider.GetSecret(context.Background(), check.ref)
  771. notes := fmt.Sprintf(setupCheckFormat, tc.setupNote, check.checkNote)
  772. if check.expectedErr == nil && err != nil {
  773. // expected no error, got one
  774. t.Errorf(getSecretErrFormat, notes, nil, err)
  775. }
  776. if check.expectedErr != nil && err == nil {
  777. // expected an error, didn't get one
  778. t.Errorf(getSecretErrFormat, notes, check.expectedErr.Error(), nil)
  779. }
  780. if check.expectedErr != nil && err != nil && err.Error() != check.expectedErr.Error() {
  781. // expected an error, got the wrong one
  782. t.Errorf(getSecretErrFormat, notes, check.expectedErr.Error(), err.Error())
  783. }
  784. if check.expectedValue != "" {
  785. if check.expectedValue != string(got) {
  786. // expected a predefined value, got something else
  787. t.Errorf(getSecretErrFormat, notes, check.expectedValue, string(got))
  788. }
  789. }
  790. }
  791. }
  792. }
  793. // most functionality is tested in TestFindItem. here we just check:
  794. // all keys are fetched and the map is compiled correctly,
  795. // files are loaded, and the data or errors are properly returned.
  796. func TestGetSecretMap(t *testing.T) {
  797. type check struct {
  798. checkNote string
  799. ref esv1beta1.ExternalSecretDataRemoteRef
  800. expectedMap map[string][]byte
  801. expectedErr error
  802. }
  803. type testCase struct {
  804. setupNote string
  805. provider *ProviderOnePassword
  806. checks []check
  807. }
  808. testCases := []testCase{
  809. {
  810. setupNote: "one vault, one item, two fields",
  811. provider: &ProviderOnePassword{
  812. vaults: map[string]int{myVault: 1},
  813. client: fake.NewMockClient().
  814. AddPredictableVault(myVault).
  815. AddPredictableItemWithField(myVault, myItem, key1, value1).
  816. AppendItemField(myVaultID, myItemID, onepassword.ItemField{
  817. Label: password,
  818. Value: value2,
  819. }),
  820. },
  821. checks: []check{
  822. {
  823. checkNote: "all Properties",
  824. ref: esv1beta1.ExternalSecretDataRemoteRef{
  825. Key: myItem,
  826. },
  827. expectedMap: map[string][]byte{
  828. key1: []byte(value1),
  829. password: []byte(value2),
  830. },
  831. expectedErr: nil,
  832. },
  833. {
  834. checkNote: "limit by Property",
  835. ref: esv1beta1.ExternalSecretDataRemoteRef{
  836. Key: myItem,
  837. Property: password,
  838. },
  839. expectedMap: map[string][]byte{
  840. password: []byte(value2),
  841. },
  842. expectedErr: nil,
  843. },
  844. {
  845. checkNote: "'ref.version' not implemented",
  846. ref: esv1beta1.ExternalSecretDataRemoteRef{
  847. Key: myItem,
  848. Property: key1,
  849. Version: "123",
  850. },
  851. expectedErr: fmt.Errorf(errVersionNotImplemented),
  852. },
  853. },
  854. },
  855. {
  856. setupNote: "files",
  857. provider: &ProviderOnePassword{
  858. vaults: map[string]int{myVault: 1},
  859. client: fake.NewMockClient().
  860. AddPredictableVault(myVault).
  861. AppendItem(myVaultID, onepassword.Item{
  862. ID: myItemID,
  863. Title: myItem,
  864. Vault: onepassword.ItemVault{ID: myVaultID},
  865. Category: documentCategory,
  866. Files: []*onepassword.File{
  867. {
  868. ID: myFilePNGID,
  869. Name: myFilePNG,
  870. },
  871. {
  872. ID: myFile2ID,
  873. Name: myFile2PNG,
  874. },
  875. },
  876. }).
  877. SetFileContents(myFilePNG, []byte(myContents)).
  878. SetFileContents(myFile2PNG, []byte(myContents2)),
  879. },
  880. checks: []check{
  881. {
  882. checkNote: "all Properties",
  883. ref: esv1beta1.ExternalSecretDataRemoteRef{
  884. Key: myItem,
  885. },
  886. expectedMap: map[string][]byte{
  887. myFilePNG: []byte(myContents),
  888. myFile2PNG: []byte(myContents2),
  889. },
  890. expectedErr: nil,
  891. },
  892. {
  893. checkNote: "limit by Property",
  894. ref: esv1beta1.ExternalSecretDataRemoteRef{
  895. Key: myItem,
  896. Property: myFilePNG,
  897. },
  898. expectedMap: map[string][]byte{
  899. myFilePNG: []byte(myContents),
  900. },
  901. expectedErr: nil,
  902. },
  903. },
  904. },
  905. {
  906. setupNote: "one vault, one item, two fields w/ same Label",
  907. provider: &ProviderOnePassword{
  908. vaults: map[string]int{myVault: 1},
  909. client: fake.NewMockClient().
  910. AddPredictableVault(myVault).
  911. AddPredictableItemWithField(myVault, myItem, key1, value1).
  912. AppendItemField(myVaultID, myItemID, onepassword.ItemField{
  913. Label: key1,
  914. Value: value2,
  915. }),
  916. },
  917. checks: []check{
  918. {
  919. checkNote: key1,
  920. ref: esv1beta1.ExternalSecretDataRemoteRef{
  921. Key: myItem,
  922. },
  923. expectedMap: nil,
  924. expectedErr: fmt.Errorf(errExpectedOneField, fmt.Errorf("'key1' in 'my-item', got 2")),
  925. },
  926. },
  927. },
  928. }
  929. // run the tests
  930. for _, tc := range testCases {
  931. for _, check := range tc.checks {
  932. gotMap, err := tc.provider.GetSecretMap(context.Background(), check.ref)
  933. notes := fmt.Sprintf(setupCheckFormat, tc.setupNote, check.checkNote)
  934. if check.expectedErr == nil && err != nil {
  935. // expected no error, got one
  936. t.Errorf(getSecretMapErrFormat, notes, nil, err)
  937. }
  938. if check.expectedErr != nil && err == nil {
  939. // expected an error, didn't get one
  940. t.Errorf(getSecretMapErrFormat, notes, check.expectedErr.Error(), nil)
  941. }
  942. if check.expectedErr != nil && err != nil && err.Error() != check.expectedErr.Error() {
  943. // expected an error, got the wrong one
  944. t.Errorf(getSecretMapErrFormat, notes, check.expectedErr.Error(), err.Error())
  945. }
  946. if !reflect.DeepEqual(check.expectedMap, gotMap) {
  947. // expected a predefined map, got something else
  948. t.Errorf(getSecretMapErrFormat, notes, check.expectedMap, gotMap)
  949. }
  950. }
  951. }
  952. }
  953. func TestGetAllSecrets(t *testing.T) {
  954. type check struct {
  955. checkNote string
  956. ref esv1beta1.ExternalSecretFind
  957. expectedMap map[string][]byte
  958. expectedErr error
  959. }
  960. type testCase struct {
  961. setupNote string
  962. provider *ProviderOnePassword
  963. checks []check
  964. }
  965. testCases := []testCase{
  966. {
  967. setupNote: "three vaults, three items, all different field Labels",
  968. provider: &ProviderOnePassword{
  969. vaults: map[string]int{myVault: 1, myOtherVault: 2, myNonMatchingVault: 3},
  970. client: fake.NewMockClient().
  971. AddPredictableVault(myVault).
  972. AddPredictableItemWithField(myVault, myItem, key1, value1).
  973. AppendItemField(myVaultID, myItemID, onepassword.ItemField{
  974. Label: key2,
  975. Value: value2,
  976. }).
  977. AddPredictableVault(myOtherVault).
  978. AddPredictableItemWithField(myOtherVault, myOtherItem, key3, value3).
  979. AppendItemField(myOtherVaultID, myOtherItemID, onepassword.ItemField{
  980. Label: key4,
  981. Value: value4,
  982. }).
  983. AddPredictableVault(myNonMatchingVault).
  984. AddPredictableItemWithField(myNonMatchingVault, myNonMatchingItem, "non-matching5", "value5").
  985. AppendItemField(myNonMatchingVaultID, myNonMatchingItemID, onepassword.ItemField{
  986. Label: "non-matching6",
  987. Value: "value6",
  988. }),
  989. },
  990. checks: []check{
  991. {
  992. checkNote: "find some with path only",
  993. ref: esv1beta1.ExternalSecretFind{
  994. Path: pointer.StringPtr(myItem),
  995. },
  996. expectedMap: map[string][]byte{
  997. key1: []byte(value1),
  998. key2: []byte(value2),
  999. },
  1000. expectedErr: nil,
  1001. },
  1002. {
  1003. checkNote: "find most with regex 'key*'",
  1004. ref: esv1beta1.ExternalSecretFind{
  1005. Name: &esv1beta1.FindName{
  1006. RegExp: "key*",
  1007. },
  1008. },
  1009. expectedMap: map[string][]byte{
  1010. key1: []byte(value1),
  1011. key2: []byte(value2),
  1012. key3: []byte(value3),
  1013. key4: []byte(value4),
  1014. },
  1015. expectedErr: nil,
  1016. },
  1017. {
  1018. checkNote: "find some with regex 'key*' and path 'my-other-item'",
  1019. ref: esv1beta1.ExternalSecretFind{
  1020. Name: &esv1beta1.FindName{
  1021. RegExp: "key*",
  1022. },
  1023. Path: pointer.StringPtr(myOtherItem),
  1024. },
  1025. expectedMap: map[string][]byte{
  1026. key3: []byte(value3),
  1027. key4: []byte(value4),
  1028. },
  1029. expectedErr: nil,
  1030. },
  1031. {
  1032. checkNote: "find none with regex 'asdf*'",
  1033. ref: esv1beta1.ExternalSecretFind{
  1034. Name: &esv1beta1.FindName{
  1035. RegExp: "asdf*",
  1036. },
  1037. },
  1038. expectedMap: map[string][]byte{},
  1039. expectedErr: nil,
  1040. },
  1041. {
  1042. checkNote: "find none with path 'no-exist'",
  1043. ref: esv1beta1.ExternalSecretFind{
  1044. Name: &esv1beta1.FindName{
  1045. RegExp: "key*",
  1046. },
  1047. Path: pointer.StringPtr("no-exist"),
  1048. },
  1049. expectedMap: map[string][]byte{},
  1050. expectedErr: nil,
  1051. },
  1052. {
  1053. checkNote: "error when find.tags",
  1054. ref: esv1beta1.ExternalSecretFind{
  1055. Name: &esv1beta1.FindName{
  1056. RegExp: "key*",
  1057. },
  1058. Tags: map[string]string{
  1059. "asdf": "fdas",
  1060. },
  1061. },
  1062. expectedErr: fmt.Errorf(errTagsNotImplemented),
  1063. },
  1064. },
  1065. },
  1066. {
  1067. setupNote: "3 vaults, 4 items, 5 files",
  1068. provider: &ProviderOnePassword{
  1069. vaults: map[string]int{myVault: 1, myOtherVault: 2, myNonMatchingVault: 3},
  1070. client: fake.NewMockClient().
  1071. // my-vault
  1072. AddPredictableVault(myVault).
  1073. AppendItem(myVaultID, onepassword.Item{
  1074. ID: myItemID,
  1075. Title: myItem,
  1076. Vault: onepassword.ItemVault{ID: myVaultID},
  1077. Category: documentCategory,
  1078. Files: []*onepassword.File{
  1079. {
  1080. ID: myFilePNGID,
  1081. Name: myFilePNG,
  1082. },
  1083. {
  1084. ID: mySecondFileTXTID,
  1085. Name: mySecondFileTXT,
  1086. },
  1087. },
  1088. }).
  1089. SetFileContents(myFilePNG, []byte(myContents)).
  1090. SetFileContents(mySecondFileTXT, []byte(mySecondContents)).
  1091. AppendItem(myVaultID, onepassword.Item{
  1092. ID: "my-item-2-id",
  1093. Title: "my-item-2",
  1094. Vault: onepassword.ItemVault{ID: myVaultID},
  1095. Category: documentCategory,
  1096. Files: []*onepassword.File{
  1097. {
  1098. ID: myFile2ID,
  1099. Name: myFile2TXT,
  1100. },
  1101. },
  1102. }).
  1103. SetFileContents(myFile2TXT, []byte(myContents2)).
  1104. // my-other-vault
  1105. AddPredictableVault(myOtherVault).
  1106. AppendItem(myOtherVaultID, onepassword.Item{
  1107. ID: myOtherItemID,
  1108. Title: myOtherItem,
  1109. Vault: onepassword.ItemVault{ID: myOtherVaultID},
  1110. Category: documentCategory,
  1111. Files: []*onepassword.File{
  1112. {
  1113. ID: myOtherFilePNGID,
  1114. Name: myOtherFilePNG,
  1115. },
  1116. },
  1117. }).
  1118. SetFileContents(myOtherFilePNG, []byte(myOtherContents)).
  1119. // my-non-matching-vault
  1120. AddPredictableVault(myNonMatchingVault).
  1121. AppendItem(myNonMatchingVaultID, onepassword.Item{
  1122. ID: myNonMatchingItemID,
  1123. Title: myNonMatchingItem,
  1124. Vault: onepassword.ItemVault{ID: myNonMatchingVaultID},
  1125. Category: documentCategory,
  1126. Files: []*onepassword.File{
  1127. {
  1128. ID: nonMatchingFilePNGID,
  1129. Name: nonMatchingFilePNG,
  1130. },
  1131. },
  1132. }).
  1133. SetFileContents(nonMatchingFilePNG, []byte(nonMatchingContents)),
  1134. },
  1135. checks: []check{
  1136. {
  1137. checkNote: "find most with regex '^my-*'",
  1138. ref: esv1beta1.ExternalSecretFind{
  1139. Name: &esv1beta1.FindName{
  1140. RegExp: "^my-*",
  1141. },
  1142. },
  1143. expectedMap: map[string][]byte{
  1144. myFilePNG: []byte(myContents),
  1145. mySecondFileTXT: []byte(mySecondContents),
  1146. myFile2TXT: []byte(myContents2),
  1147. myOtherFilePNG: []byte(myOtherContents),
  1148. },
  1149. expectedErr: nil,
  1150. },
  1151. {
  1152. checkNote: "find some with regex '^my-*' and path 'my-other-item'",
  1153. ref: esv1beta1.ExternalSecretFind{
  1154. Name: &esv1beta1.FindName{
  1155. RegExp: "^my-*",
  1156. },
  1157. Path: pointer.StringPtr(myOtherItem),
  1158. },
  1159. expectedMap: map[string][]byte{
  1160. myOtherFilePNG: []byte(myOtherContents),
  1161. },
  1162. expectedErr: nil,
  1163. },
  1164. {
  1165. checkNote: "find none with regex '^asdf*'",
  1166. ref: esv1beta1.ExternalSecretFind{
  1167. Name: &esv1beta1.FindName{
  1168. RegExp: "^asdf*",
  1169. },
  1170. },
  1171. expectedMap: map[string][]byte{},
  1172. expectedErr: nil,
  1173. },
  1174. {
  1175. checkNote: "find none with path 'no-exist'",
  1176. ref: esv1beta1.ExternalSecretFind{
  1177. Name: &esv1beta1.FindName{
  1178. RegExp: "^my-*",
  1179. },
  1180. Path: pointer.StringPtr("no-exist"),
  1181. },
  1182. expectedMap: map[string][]byte{},
  1183. expectedErr: nil,
  1184. },
  1185. },
  1186. },
  1187. {
  1188. setupNote: "two fields/files with same name, first one wins",
  1189. provider: &ProviderOnePassword{
  1190. vaults: map[string]int{myVault: 1, myOtherVault: 2},
  1191. client: fake.NewMockClient().
  1192. // my-vault
  1193. AddPredictableVault(myVault).
  1194. AddPredictableItemWithField(myVault, myItem, key1, value1).
  1195. AddPredictableItemWithField(myVault, "my-second-item", key1, "value-second").
  1196. AppendItem(myVaultID, onepassword.Item{
  1197. ID: "file-item-id",
  1198. Title: "file-item",
  1199. Vault: onepassword.ItemVault{ID: myVaultID},
  1200. Category: documentCategory,
  1201. Files: []*onepassword.File{
  1202. {
  1203. ID: filePNGID,
  1204. Name: filePNG,
  1205. },
  1206. },
  1207. }).
  1208. SetFileContents(filePNG, []byte(myContents)).
  1209. AppendItem(myVaultID, onepassword.Item{
  1210. ID: "file-item-2-id",
  1211. Title: "file-item-2",
  1212. Vault: onepassword.ItemVault{ID: myVaultID},
  1213. Category: documentCategory,
  1214. Files: []*onepassword.File{
  1215. {
  1216. ID: "file-2-id",
  1217. Name: filePNG,
  1218. },
  1219. },
  1220. }).
  1221. // my-other-vault
  1222. AddPredictableVault(myOtherVault).
  1223. AddPredictableItemWithField(myOtherVault, myOtherItem, key1, "value-other").
  1224. AppendItem(myOtherVaultID, onepassword.Item{
  1225. ID: "file-item-other-id",
  1226. Title: "file-item-other",
  1227. Vault: onepassword.ItemVault{ID: myOtherVaultID},
  1228. Category: documentCategory,
  1229. Files: []*onepassword.File{
  1230. {
  1231. ID: "other-file-id",
  1232. Name: filePNG,
  1233. },
  1234. },
  1235. }),
  1236. },
  1237. checks: []check{
  1238. {
  1239. checkNote: "find fields with regex '^key*'",
  1240. ref: esv1beta1.ExternalSecretFind{
  1241. Name: &esv1beta1.FindName{
  1242. RegExp: "^key*",
  1243. },
  1244. },
  1245. expectedMap: map[string][]byte{
  1246. key1: []byte(value1),
  1247. },
  1248. expectedErr: nil,
  1249. },
  1250. {
  1251. checkNote: "find files with regex '^file*item*'",
  1252. ref: esv1beta1.ExternalSecretFind{
  1253. Name: &esv1beta1.FindName{
  1254. RegExp: "^file*",
  1255. },
  1256. },
  1257. expectedMap: map[string][]byte{
  1258. filePNG: []byte(myContents),
  1259. },
  1260. expectedErr: nil,
  1261. },
  1262. },
  1263. },
  1264. }
  1265. // run the tests
  1266. for _, tc := range testCases {
  1267. for _, check := range tc.checks {
  1268. gotMap, err := tc.provider.GetAllSecrets(context.Background(), check.ref)
  1269. notes := fmt.Sprintf(setupCheckFormat, tc.setupNote, check.checkNote)
  1270. if check.expectedErr == nil && err != nil {
  1271. // expected no error, got one
  1272. t.Fatalf(getAllSecretsErrFormat, notes, nil, err)
  1273. }
  1274. if check.expectedErr != nil && err == nil {
  1275. // expected an error, didn't get one
  1276. t.Errorf(getAllSecretsErrFormat, notes, check.expectedErr.Error(), nil)
  1277. }
  1278. if check.expectedErr != nil && err != nil && err.Error() != check.expectedErr.Error() {
  1279. // expected an error, got the wrong one
  1280. t.Errorf(getAllSecretsErrFormat, notes, check.expectedErr.Error(), err.Error())
  1281. }
  1282. if !reflect.DeepEqual(check.expectedMap, gotMap) {
  1283. // expected a predefined map, got something else
  1284. t.Errorf(getAllSecretsErrFormat, notes, check.expectedMap, gotMap)
  1285. }
  1286. }
  1287. }
  1288. }
  1289. func TestSortVaults(t *testing.T) {
  1290. type testCase struct {
  1291. vaults map[string]int
  1292. expected []string
  1293. }
  1294. testCases := []testCase{
  1295. {
  1296. vaults: map[string]int{
  1297. one: 1,
  1298. three: 3,
  1299. two: 2,
  1300. },
  1301. expected: []string{
  1302. one,
  1303. two,
  1304. three,
  1305. },
  1306. },
  1307. {
  1308. vaults: map[string]int{
  1309. "four": 100,
  1310. one: 1,
  1311. three: 3,
  1312. two: 2,
  1313. },
  1314. expected: []string{
  1315. one,
  1316. two,
  1317. three,
  1318. "four",
  1319. },
  1320. },
  1321. }
  1322. // run the tests
  1323. for _, tc := range testCases {
  1324. got := sortVaults(tc.vaults)
  1325. if !reflect.DeepEqual(got, tc.expected) {
  1326. t.Errorf("onepassword.sortVaults(...): -expected, +got:\n-%#v\n+%#v\n", tc.expected, got)
  1327. }
  1328. }
  1329. }
  1330. func TestHasUniqueVaultNumbers(t *testing.T) {
  1331. type testCase struct {
  1332. vaults map[string]int
  1333. expected bool
  1334. }
  1335. testCases := []testCase{
  1336. {
  1337. vaults: map[string]int{
  1338. one: 1,
  1339. three: 3,
  1340. two: 2,
  1341. },
  1342. expected: true,
  1343. },
  1344. {
  1345. vaults: map[string]int{
  1346. "four": 100,
  1347. one: 1,
  1348. three: 3,
  1349. two: 2,
  1350. "eight": 100,
  1351. },
  1352. expected: false,
  1353. },
  1354. {
  1355. vaults: map[string]int{
  1356. one: 1,
  1357. "1": 1,
  1358. three: 3,
  1359. two: 2,
  1360. },
  1361. expected: false,
  1362. },
  1363. }
  1364. // run the tests
  1365. for _, tc := range testCases {
  1366. got := hasUniqueVaultNumbers(tc.vaults)
  1367. if got != tc.expected {
  1368. t.Errorf("onepassword.hasUniqueVaultNumbers(...): -expected, +got:\n-%#v\n+%#v\n", tc.expected, got)
  1369. }
  1370. }
  1371. }