provider_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  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 dvls
  14. import (
  15. "testing"
  16. "github.com/stretchr/testify/assert"
  17. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  18. esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
  19. esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
  20. )
  21. const (
  22. testNamespace = "default"
  23. testServerURL = "https://dvls.example.com"
  24. secretName = "dvls-secret"
  25. appIDKey = "app-id"
  26. appSecretKey = "app-secret"
  27. otherNS = "other"
  28. testAppID = "test-app-id"
  29. testAppSecret = "test-app-secret"
  30. )
  31. func TestProvider_ValidateStore(t *testing.T) {
  32. p := &Provider{}
  33. t.Run("case 1: should return no error when valid", func(t *testing.T) {
  34. store := &esv1.SecretStore{
  35. ObjectMeta: metav1.ObjectMeta{
  36. Name: "dvls-store",
  37. Namespace: testNamespace,
  38. },
  39. Spec: esv1.SecretStoreSpec{
  40. Provider: &esv1.SecretStoreProvider{
  41. DVLS: &esv1.DVLSProvider{
  42. ServerURL: testServerURL,
  43. Auth: esv1.DVLSAuth{
  44. SecretRef: esv1.DVLSAuthSecretRef{
  45. AppID: esmeta.SecretKeySelector{
  46. Name: secretName,
  47. Key: appIDKey,
  48. },
  49. AppSecret: esmeta.SecretKeySelector{
  50. Name: secretName,
  51. Key: appSecretKey,
  52. },
  53. },
  54. },
  55. },
  56. },
  57. },
  58. }
  59. _, err := p.ValidateStore(store)
  60. assert.NoError(t, err)
  61. })
  62. t.Run("case 1b: cluster store requires namespace", func(t *testing.T) {
  63. store := &esv1.ClusterSecretStore{
  64. TypeMeta: metav1.TypeMeta{Kind: "ClusterSecretStore"},
  65. ObjectMeta: metav1.ObjectMeta{
  66. Name: "dvls-cluster-store",
  67. },
  68. Spec: esv1.SecretStoreSpec{
  69. Provider: &esv1.SecretStoreProvider{
  70. DVLS: &esv1.DVLSProvider{
  71. ServerURL: testServerURL,
  72. Auth: esv1.DVLSAuth{
  73. SecretRef: esv1.DVLSAuthSecretRef{
  74. AppID: esmeta.SecretKeySelector{
  75. Name: secretName,
  76. Key: appIDKey,
  77. },
  78. AppSecret: esmeta.SecretKeySelector{
  79. Name: secretName,
  80. Key: appSecretKey,
  81. },
  82. },
  83. },
  84. },
  85. },
  86. },
  87. }
  88. _, err := p.ValidateStore(store)
  89. assert.Error(t, err)
  90. assert.Contains(t, err.Error(), "cluster scope requires namespace")
  91. })
  92. t.Run("case 1c: cluster store succeeds with namespace", func(t *testing.T) {
  93. otherNamespace := otherNS
  94. store := &esv1.ClusterSecretStore{
  95. TypeMeta: metav1.TypeMeta{Kind: "ClusterSecretStore"},
  96. ObjectMeta: metav1.ObjectMeta{
  97. Name: "dvls-cluster-store",
  98. },
  99. Spec: esv1.SecretStoreSpec{
  100. Provider: &esv1.SecretStoreProvider{
  101. DVLS: &esv1.DVLSProvider{
  102. ServerURL: testServerURL,
  103. Auth: esv1.DVLSAuth{
  104. SecretRef: esv1.DVLSAuthSecretRef{
  105. AppID: esmeta.SecretKeySelector{
  106. Name: secretName,
  107. Key: appIDKey,
  108. Namespace: &otherNamespace,
  109. },
  110. AppSecret: esmeta.SecretKeySelector{
  111. Name: secretName,
  112. Key: appSecretKey,
  113. Namespace: &otherNamespace,
  114. },
  115. },
  116. },
  117. },
  118. },
  119. },
  120. }
  121. _, err := p.ValidateStore(store)
  122. assert.NoError(t, err)
  123. })
  124. t.Run("case 2: should return error when provider is nil", func(t *testing.T) {
  125. store := &esv1.SecretStore{
  126. Spec: esv1.SecretStoreSpec{
  127. Provider: &esv1.SecretStoreProvider{
  128. DVLS: nil,
  129. },
  130. },
  131. }
  132. _, err := p.ValidateStore(store)
  133. assert.Error(t, err)
  134. assert.Contains(t, err.Error(), "DVLS provider configuration is missing")
  135. })
  136. t.Run("case 2b: http URL without insecure flag should fail", func(t *testing.T) {
  137. store := &esv1.SecretStore{
  138. ObjectMeta: metav1.ObjectMeta{
  139. Name: "dvls-store",
  140. Namespace: testNamespace,
  141. },
  142. Spec: esv1.SecretStoreSpec{
  143. Provider: &esv1.SecretStoreProvider{
  144. DVLS: &esv1.DVLSProvider{
  145. ServerURL: "http://dvls.example.com",
  146. Auth: esv1.DVLSAuth{
  147. SecretRef: esv1.DVLSAuthSecretRef{
  148. AppID: esmeta.SecretKeySelector{
  149. Name: secretName,
  150. Key: appIDKey,
  151. },
  152. AppSecret: esmeta.SecretKeySelector{
  153. Name: secretName,
  154. Key: appSecretKey,
  155. },
  156. },
  157. },
  158. },
  159. },
  160. },
  161. }
  162. _, err := p.ValidateStore(store)
  163. assert.Error(t, err)
  164. assert.Contains(t, err.Error(), "http URLs require 'insecure: true'")
  165. })
  166. t.Run("case 2c: http URL with insecure flag should pass", func(t *testing.T) {
  167. store := &esv1.SecretStore{
  168. ObjectMeta: metav1.ObjectMeta{
  169. Name: "dvls-store",
  170. Namespace: testNamespace,
  171. },
  172. Spec: esv1.SecretStoreSpec{
  173. Provider: &esv1.SecretStoreProvider{
  174. DVLS: &esv1.DVLSProvider{
  175. ServerURL: "http://dvls.example.com",
  176. Insecure: true,
  177. Auth: esv1.DVLSAuth{
  178. SecretRef: esv1.DVLSAuthSecretRef{
  179. AppID: esmeta.SecretKeySelector{
  180. Name: secretName,
  181. Key: appIDKey,
  182. },
  183. AppSecret: esmeta.SecretKeySelector{
  184. Name: secretName,
  185. Key: appSecretKey,
  186. },
  187. },
  188. },
  189. },
  190. },
  191. },
  192. }
  193. _, err := p.ValidateStore(store)
  194. assert.NoError(t, err)
  195. })
  196. t.Run("case 3: should return error when serverUrl is empty", func(t *testing.T) {
  197. store := &esv1.SecretStore{
  198. ObjectMeta: metav1.ObjectMeta{
  199. Name: "dvls-store",
  200. Namespace: testNamespace,
  201. },
  202. Spec: esv1.SecretStoreSpec{
  203. Provider: &esv1.SecretStoreProvider{
  204. DVLS: &esv1.DVLSProvider{
  205. ServerURL: "",
  206. Auth: esv1.DVLSAuth{
  207. SecretRef: esv1.DVLSAuthSecretRef{
  208. AppID: esmeta.SecretKeySelector{
  209. Name: secretName,
  210. Key: appIDKey,
  211. },
  212. AppSecret: esmeta.SecretKeySelector{
  213. Name: secretName,
  214. Key: appSecretKey,
  215. },
  216. },
  217. },
  218. },
  219. },
  220. },
  221. }
  222. _, err := p.ValidateStore(store)
  223. assert.Error(t, err)
  224. assert.Contains(t, err.Error(), "serverUrl is required")
  225. })
  226. t.Run("case 3b: should return error when appId key is missing", func(t *testing.T) {
  227. store := &esv1.SecretStore{
  228. ObjectMeta: metav1.ObjectMeta{
  229. Name: "dvls-store",
  230. Namespace: testNamespace,
  231. },
  232. Spec: esv1.SecretStoreSpec{
  233. Provider: &esv1.SecretStoreProvider{
  234. DVLS: &esv1.DVLSProvider{
  235. ServerURL: testServerURL,
  236. Auth: esv1.DVLSAuth{
  237. SecretRef: esv1.DVLSAuthSecretRef{
  238. AppID: esmeta.SecretKeySelector{
  239. Name: secretName,
  240. Key: "",
  241. },
  242. AppSecret: esmeta.SecretKeySelector{
  243. Name: secretName,
  244. Key: appSecretKey,
  245. },
  246. },
  247. },
  248. },
  249. },
  250. },
  251. }
  252. _, err := p.ValidateStore(store)
  253. assert.Error(t, err)
  254. assert.Contains(t, err.Error(), "appId secret key is required")
  255. })
  256. t.Run("case 3c: should return error when appSecret name is missing", func(t *testing.T) {
  257. store := &esv1.SecretStore{
  258. ObjectMeta: metav1.ObjectMeta{
  259. Name: "dvls-store",
  260. Namespace: testNamespace,
  261. },
  262. Spec: esv1.SecretStoreSpec{
  263. Provider: &esv1.SecretStoreProvider{
  264. DVLS: &esv1.DVLSProvider{
  265. ServerURL: testServerURL,
  266. Auth: esv1.DVLSAuth{
  267. SecretRef: esv1.DVLSAuthSecretRef{
  268. AppID: esmeta.SecretKeySelector{
  269. Name: secretName,
  270. Key: appIDKey,
  271. },
  272. AppSecret: esmeta.SecretKeySelector{
  273. Name: "",
  274. Key: appSecretKey,
  275. },
  276. },
  277. },
  278. },
  279. },
  280. },
  281. }
  282. _, err := p.ValidateStore(store)
  283. assert.Error(t, err)
  284. assert.Contains(t, err.Error(), "appSecret secret name is required")
  285. })
  286. t.Run("case 4: should return error when AppID secret reference is invalid", func(t *testing.T) {
  287. otherNamespace := otherNS
  288. store := &esv1.SecretStore{
  289. ObjectMeta: metav1.ObjectMeta{
  290. Name: "dvls-store",
  291. Namespace: testNamespace,
  292. },
  293. Spec: esv1.SecretStoreSpec{
  294. Provider: &esv1.SecretStoreProvider{
  295. DVLS: &esv1.DVLSProvider{
  296. ServerURL: testServerURL,
  297. Auth: esv1.DVLSAuth{
  298. SecretRef: esv1.DVLSAuthSecretRef{
  299. AppID: esmeta.SecretKeySelector{
  300. Name: secretName,
  301. Key: appIDKey,
  302. Namespace: &otherNamespace,
  303. },
  304. AppSecret: esmeta.SecretKeySelector{
  305. Name: secretName,
  306. Key: appSecretKey,
  307. },
  308. },
  309. },
  310. },
  311. },
  312. },
  313. }
  314. _, err := p.ValidateStore(store)
  315. assert.Error(t, err)
  316. assert.Contains(t, err.Error(), "invalid appId")
  317. })
  318. t.Run("case 5: should return error when AppSecret secret reference is invalid", func(t *testing.T) {
  319. otherNamespace := otherNS
  320. store := &esv1.SecretStore{
  321. ObjectMeta: metav1.ObjectMeta{
  322. Name: "dvls-store",
  323. Namespace: testNamespace,
  324. },
  325. Spec: esv1.SecretStoreSpec{
  326. Provider: &esv1.SecretStoreProvider{
  327. DVLS: &esv1.DVLSProvider{
  328. ServerURL: testServerURL,
  329. Auth: esv1.DVLSAuth{
  330. SecretRef: esv1.DVLSAuthSecretRef{
  331. AppID: esmeta.SecretKeySelector{
  332. Name: secretName,
  333. Key: appIDKey,
  334. },
  335. AppSecret: esmeta.SecretKeySelector{
  336. Name: secretName,
  337. Key: appSecretKey,
  338. Namespace: &otherNamespace,
  339. },
  340. },
  341. },
  342. },
  343. },
  344. },
  345. }
  346. _, err := p.ValidateStore(store)
  347. assert.Error(t, err)
  348. assert.Contains(t, err.Error(), "invalid appSecret")
  349. })
  350. }
  351. func TestProvider_Capabilities(t *testing.T) {
  352. p := &Provider{}
  353. assert.Equal(t, esv1.SecretStoreReadWrite, p.Capabilities())
  354. }
  355. func TestNewProvider(t *testing.T) {
  356. p := NewProvider()
  357. assert.NotNil(t, p)
  358. _, ok := p.(*Provider)
  359. assert.True(t, ok)
  360. }
  361. func TestProviderSpec(t *testing.T) {
  362. spec := ProviderSpec()
  363. assert.NotNil(t, spec)
  364. assert.NotNil(t, spec.DVLS)
  365. }
  366. func TestMaintenanceStatus(t *testing.T) {
  367. status := MaintenanceStatus()
  368. assert.Equal(t, esv1.MaintenanceStatusMaintained, status)
  369. }