passworddepot_api_test.go 7.6 KB

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