passworddepot_api_test.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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 passworddepot
  13. import (
  14. "bytes"
  15. "encoding/json"
  16. "io"
  17. "net/http"
  18. "reflect"
  19. "testing"
  20. "time"
  21. fakepassworddepot "github.com/external-secrets/external-secrets/pkg/provider/passworddepot/fake"
  22. )
  23. const fingerprint1 = "53fe39bd-0d5c-4b46-83b3-122fef14364e"
  24. const mySecret = "my-secret"
  25. const someDB = "some-db"
  26. var (
  27. mockDatabaseList = Databases{
  28. Databases: []struct {
  29. Name string `json:"name"`
  30. Fingerprint string `json:"fingerprint"`
  31. Date time.Time `json:"date"`
  32. Rights string `json:"rights"`
  33. Reasondelete string `json:"reasondelete"`
  34. }{
  35. {
  36. Name: someDB,
  37. Fingerprint: "434da246-c165-499b-8996-6ee2a9673429",
  38. },
  39. },
  40. }
  41. mockDatabaseEntries = DatabaseEntries{
  42. Entries: []Entry{
  43. {
  44. Name: mySecret,
  45. Fingerprint: fingerprint1,
  46. },
  47. },
  48. }
  49. )
  50. func TestPasswortDepotApiListDatabases(t *testing.T) {
  51. type fields struct {
  52. funcStack []func(req *http.Request) (*http.Response, error)
  53. }
  54. tests := []struct {
  55. name string
  56. fields fields
  57. want Databases
  58. wantErr bool
  59. }{
  60. {
  61. name: "list databases",
  62. fields: fields{
  63. funcStack: []func(req *http.Request) (*http.Response, error){
  64. createResponder(mockDatabaseList, true), //nolint:bodyclose // linters bug
  65. },
  66. },
  67. want: Databases{
  68. Databases: []struct {
  69. Name string `json:"name"`
  70. Fingerprint string `json:"fingerprint"`
  71. Date time.Time `json:"date"`
  72. Rights string `json:"rights"`
  73. Reasondelete string `json:"reasondelete"`
  74. }{
  75. {
  76. Name: someDB,
  77. Fingerprint: "434da246-c165-499b-8996-6ee2a9673429",
  78. },
  79. },
  80. },
  81. wantErr: false,
  82. },
  83. {
  84. name: "bad response body",
  85. fields: fields{
  86. funcStack: []func(req *http.Request) (*http.Response, error){
  87. createResponder([]byte("bad response"), false), //nolint:bodyclose // linters bug
  88. },
  89. },
  90. want: Databases{},
  91. wantErr: true,
  92. },
  93. }
  94. for _, tt := range tests {
  95. t.Run(tt.name, func(t *testing.T) {
  96. api := &API{
  97. client: &fakepassworddepot.MockClient{
  98. FuncStack: tt.fields.funcStack,
  99. },
  100. baseURL: "localhost",
  101. hostPort: "8714",
  102. password: "test",
  103. username: "test",
  104. secret: &AccessData{
  105. ClientID: "12345",
  106. AccessToken: "f02a1f7c-7629-422e-96f5-a98b29da1287",
  107. },
  108. }
  109. got, err := api.ListDatabases()
  110. if (err != nil) != tt.wantErr {
  111. t.Errorf("PasswortDepotApi.ListDatabases() error = %v, wantErr %v", err, tt.wantErr)
  112. return
  113. }
  114. if !reflect.DeepEqual(got, tt.want) {
  115. t.Errorf("PasswortDepotApi.ListDatabases() = %v, want %v", got, tt.want)
  116. }
  117. })
  118. }
  119. }
  120. func TestPasswortDepotApiGetSecret(t *testing.T) {
  121. type fields struct {
  122. funcStack []func(req *http.Request) (*http.Response, error)
  123. }
  124. type args struct {
  125. database string
  126. secretName string
  127. }
  128. tests := []struct {
  129. name string
  130. fields fields
  131. args args
  132. want SecretEntry
  133. wantErr bool
  134. }{
  135. {
  136. name: "get secret",
  137. fields: fields{
  138. funcStack: []func(req *http.Request) (*http.Response, error){
  139. createResponder(mockDatabaseList, true), //nolint:bodyclose // linters bug
  140. createResponder(mockDatabaseEntries, true), //nolint:bodyclose // linters bug
  141. createResponder(SecretEntry{ //nolint:bodyclose // linters bug
  142. Name: mySecret,
  143. Fingerprint: fingerprint1,
  144. Pass: "yery53cr3t",
  145. }, true),
  146. },
  147. },
  148. args: args{
  149. database: someDB,
  150. secretName: mySecret,
  151. },
  152. want: SecretEntry{
  153. Name: mySecret,
  154. Fingerprint: fingerprint1,
  155. Pass: "yery53cr3t",
  156. },
  157. wantErr: false,
  158. },
  159. {
  160. name: "get nested secret",
  161. fields: fields{
  162. funcStack: []func(req *http.Request) (*http.Response, error){
  163. createResponder(mockDatabaseList, true), //nolint:bodyclose // linters bug
  164. createResponder(DatabaseEntries{ //nolint:bodyclose // linters bug
  165. Entries: []Entry{
  166. {
  167. Name: "Production",
  168. Fingerprint: "33f918ae-ec60-41cb-8131-67d8f21eef4c",
  169. },
  170. },
  171. }, true),
  172. createResponder(mockDatabaseEntries, true), //nolint:bodyclose // linters bug
  173. createResponder(SecretEntry{ //nolint:bodyclose // linters bug
  174. Name: mySecret,
  175. Fingerprint: fingerprint1,
  176. Pass: "yery53cr3t",
  177. }, true),
  178. },
  179. },
  180. args: args{
  181. database: someDB,
  182. secretName: "Production.my-secret",
  183. },
  184. want: SecretEntry{
  185. Name: mySecret,
  186. Fingerprint: fingerprint1,
  187. Pass: "yery53cr3t",
  188. },
  189. wantErr: false,
  190. },
  191. {
  192. name: "bad response body on database entries",
  193. fields: fields{
  194. funcStack: []func(req *http.Request) (*http.Response, error){
  195. createResponder(mockDatabaseList, true), //nolint:bodyclose // linters bug
  196. createResponder([]byte("bad body"), false), //nolint:bodyclose // linters bug
  197. },
  198. },
  199. args: args{
  200. database: someDB,
  201. secretName: mySecret,
  202. },
  203. want: SecretEntry{},
  204. wantErr: true,
  205. },
  206. {
  207. name: "bad response on secret entry",
  208. fields: fields{
  209. funcStack: []func(req *http.Request) (*http.Response, error){
  210. createResponder(mockDatabaseList, true), //nolint:bodyclose // linters bug
  211. createResponder(mockDatabaseEntries, true), //nolint:bodyclose // linters bug
  212. createResponder([]byte("bad response body"), false), //nolint:bodyclose // linters bug
  213. },
  214. },
  215. args: args{
  216. database: someDB,
  217. secretName: mySecret,
  218. },
  219. want: SecretEntry{},
  220. wantErr: true,
  221. },
  222. {
  223. name: "no secret with name",
  224. fields: fields{
  225. funcStack: []func(req *http.Request) (*http.Response, error){
  226. createResponder(mockDatabaseList, true), //nolint:bodyclose // linters bug
  227. createResponder(DatabaseEntries{Entries: []Entry{}}, true), //nolint:bodyclose // linters bug
  228. },
  229. },
  230. args: args{
  231. database: someDB,
  232. secretName: mySecret,
  233. },
  234. want: SecretEntry{},
  235. wantErr: true,
  236. },
  237. }
  238. for _, tt := range tests {
  239. t.Run(tt.name, func(t *testing.T) {
  240. api := &API{
  241. client: &fakepassworddepot.MockClient{
  242. FuncStack: tt.fields.funcStack,
  243. },
  244. baseURL: "localhost",
  245. hostPort: "8714",
  246. password: "test",
  247. username: "test",
  248. secret: &AccessData{
  249. ClientID: "12345",
  250. AccessToken: "f02a1f7c-7629-422e-96f5-a98b29da1287",
  251. },
  252. }
  253. got, err := api.GetSecret(tt.args.database, tt.args.secretName)
  254. if (err != nil) != tt.wantErr {
  255. t.Errorf("PasswortDepotApi.GetSecret() error = %v, wantErr %v", err, tt.wantErr)
  256. return
  257. }
  258. if !reflect.DeepEqual(got, tt.want) {
  259. t.Errorf("PasswortDepotApi.GetSecret() = %v, want %v", got, tt.want)
  260. }
  261. })
  262. }
  263. }
  264. func createResponder(payload any, withMarshal bool) func(*http.Request) (*http.Response, error) {
  265. return func(req *http.Request) (*http.Response, error) {
  266. var payloadBytes []byte
  267. if withMarshal {
  268. payloadBytes, _ = json.Marshal(payload)
  269. } else {
  270. payloadBytes = payload.([]byte)
  271. }
  272. res := http.Response{
  273. Status: "OK",
  274. StatusCode: http.StatusOK,
  275. Body: io.NopCloser(bytes.NewReader(payloadBytes)),
  276. }
  277. return &res, nil
  278. }
  279. }