common.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  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. limitations under the License.
  10. */
  11. package common
  12. import (
  13. "fmt"
  14. v1 "k8s.io/api/core/v1"
  15. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  16. esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
  17. "github.com/external-secrets/external-secrets/e2e/framework"
  18. )
  19. // This case creates multiple secrets with simple key/value pairs and syncs them using multiple .Spec.Data blocks.
  20. // Not supported by: vault.
  21. func SimpleDataSync(f *framework.Framework) (string, func(*framework.TestCase)) {
  22. return "[common] should sync simple secrets from .Data[]", func(tc *framework.TestCase) {
  23. secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one")
  24. secretKey2 := fmt.Sprintf("%s-%s", f.Namespace.Name, "other")
  25. secretValue := "bar"
  26. tc.Secrets = map[string]string{
  27. secretKey1: secretValue,
  28. secretKey2: secretValue,
  29. }
  30. tc.ExpectedSecret = &v1.Secret{
  31. Type: v1.SecretTypeOpaque,
  32. Data: map[string][]byte{
  33. secretKey1: []byte(secretValue),
  34. secretKey2: []byte(secretValue),
  35. },
  36. }
  37. tc.ExternalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{
  38. {
  39. SecretKey: secretKey1,
  40. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  41. Key: secretKey1,
  42. },
  43. },
  44. {
  45. SecretKey: secretKey2,
  46. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  47. Key: secretKey2,
  48. },
  49. },
  50. }
  51. }
  52. }
  53. // This case creates multiple secrets with json values and syncs them using multiple .Spec.Data blocks.
  54. // The data is extracted from the JSON key using ref.Property.
  55. func JSONDataWithProperty(f *framework.Framework) (string, func(*framework.TestCase)) {
  56. return "[common] should sync multiple secrets from .Data[]", func(tc *framework.TestCase) {
  57. secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one")
  58. secretKey2 := fmt.Sprintf("%s-%s", f.Namespace.Name, "two")
  59. secretValue1 := "{\"foo1\":\"foo1-val\",\"bar1\":\"bar1-val\"}"
  60. secretValue2 := "{\"foo2\":\"foo2-val\",\"bar2\":\"bar2-val\"}"
  61. tc.Secrets = map[string]string{
  62. secretKey1: secretValue1,
  63. secretKey2: secretValue2,
  64. }
  65. tc.ExpectedSecret = &v1.Secret{
  66. Type: v1.SecretTypeOpaque,
  67. Data: map[string][]byte{
  68. secretKey1: []byte("foo1-val"),
  69. secretKey2: []byte("bar2-val"),
  70. },
  71. }
  72. tc.ExternalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{
  73. {
  74. SecretKey: secretKey1,
  75. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  76. Key: secretKey1,
  77. Property: "foo1",
  78. },
  79. },
  80. {
  81. SecretKey: secretKey2,
  82. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  83. Key: secretKey2,
  84. Property: "bar2",
  85. },
  86. },
  87. }
  88. }
  89. }
  90. // This case creates multiple secrets with json values and renders a template.
  91. // The data is extracted from the JSON key using ref.Property.
  92. func JSONDataWithTemplate(f *framework.Framework) (string, func(*framework.TestCase)) {
  93. return "[common] should sync json secrets with template", func(tc *framework.TestCase) {
  94. secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one")
  95. secretKey2 := fmt.Sprintf("%s-%s", f.Namespace.Name, "other")
  96. secretValue1 := "{\"foo1\":\"foo1-val\",\"bar1\":\"bar1-val\"}"
  97. secretValue2 := "{\"foo2\":\"foo2-val\",\"bar2\":\"bar2-val\"}"
  98. tc.Secrets = map[string]string{
  99. secretKey1: secretValue1,
  100. secretKey2: secretValue2,
  101. }
  102. tc.ExpectedSecret = &v1.Secret{
  103. Type: v1.SecretTypeOpaque,
  104. ObjectMeta: metav1.ObjectMeta{
  105. Annotations: map[string]string{
  106. "example": "annotation",
  107. },
  108. Labels: map[string]string{
  109. "example": "label",
  110. },
  111. },
  112. Data: map[string][]byte{
  113. "my-data": []byte(`executed: foo1-val|bar2-val`),
  114. },
  115. }
  116. tc.ExternalSecret.Spec.Target.Template = &esv1alpha1.ExternalSecretTemplate{
  117. Metadata: esv1alpha1.ExternalSecretTemplateMetadata{
  118. Annotations: map[string]string{
  119. "example": "annotation",
  120. },
  121. Labels: map[string]string{
  122. "example": "label",
  123. },
  124. },
  125. Data: map[string]string{
  126. "my-data": "executed: {{ .one | toString }}|{{ .two | toString }}",
  127. },
  128. }
  129. tc.ExternalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{
  130. {
  131. SecretKey: "one",
  132. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  133. Key: secretKey1,
  134. Property: "foo1",
  135. },
  136. },
  137. {
  138. SecretKey: "two",
  139. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  140. Key: secretKey2,
  141. Property: "bar2",
  142. },
  143. },
  144. }
  145. }
  146. }
  147. // This case creates one secret with json values and syncs them using a single .Spec.DataFrom block.
  148. func JSONDataFromSync(f *framework.Framework) (string, func(*framework.TestCase)) {
  149. return "[common] should sync secrets with dataFrom", func(tc *framework.TestCase) {
  150. secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one")
  151. targetSecretKey1 := "name"
  152. targetSecretValue1 := "great-name"
  153. targetSecretKey2 := "surname"
  154. targetSecretValue2 := "great-surname"
  155. secretValue := fmt.Sprintf("{ \"%s\": \"%s\", \"%s\": \"%s\" }", targetSecretKey1, targetSecretValue1, targetSecretKey2, targetSecretValue2)
  156. tc.Secrets = map[string]string{
  157. secretKey1: secretValue,
  158. }
  159. tc.ExpectedSecret = &v1.Secret{
  160. Type: v1.SecretTypeOpaque,
  161. Data: map[string][]byte{
  162. targetSecretKey1: []byte(targetSecretValue1),
  163. targetSecretKey2: []byte(targetSecretValue2),
  164. },
  165. }
  166. tc.ExternalSecret.Spec.DataFrom = []esv1alpha1.ExternalSecretDataRemoteRef{
  167. {
  168. Key: secretKey1,
  169. },
  170. }
  171. }
  172. }
  173. // This case creates a secret with a nested json value. It is synced into two secrets.
  174. // The values from the nested data are extracted using gjson.
  175. // not supported by: vault.
  176. func NestedJSONWithGJSON(f *framework.Framework) (string, func(*framework.TestCase)) {
  177. return "[common] should sync nested json secrets and get inner keys", func(tc *framework.TestCase) {
  178. secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one")
  179. targetSecretKey1 := "firstname"
  180. targetSecretValue1 := "Tom"
  181. targetSecretKey2 := "first_friend"
  182. targetSecretValue2 := "Roger"
  183. secretValue := fmt.Sprintf(
  184. `{
  185. "name": {"first": "%s", "last": "Anderson"},
  186. "friends":
  187. [
  188. {"first": "Dale", "last": "Murphy"},
  189. {"first": "%s", "last": "Craig"},
  190. {"first": "Jane", "last": "Murphy"}
  191. ]
  192. }`, targetSecretValue1, targetSecretValue2)
  193. tc.Secrets = map[string]string{
  194. secretKey1: secretValue,
  195. }
  196. tc.ExpectedSecret = &v1.Secret{
  197. Type: v1.SecretTypeOpaque,
  198. Data: map[string][]byte{
  199. targetSecretKey1: []byte(targetSecretValue1),
  200. targetSecretKey2: []byte(targetSecretValue2),
  201. },
  202. }
  203. tc.ExternalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{
  204. {
  205. SecretKey: targetSecretKey1,
  206. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  207. Key: secretKey1,
  208. Property: "name.first",
  209. },
  210. },
  211. {
  212. SecretKey: targetSecretKey2,
  213. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  214. Key: secretKey1,
  215. Property: "friends.1.first",
  216. },
  217. },
  218. }
  219. }
  220. }
  221. // This case creates a secret with a Docker json configuration value.
  222. // The values from the nested data are extracted using gjson.
  223. // not supported by: vault.
  224. func DockerJSONConfig(f *framework.Framework) (string, func(*framework.TestCase)) {
  225. return "[common] should sync docker configurated json secrets with template simple", func(tc *framework.TestCase) {
  226. cloudSecretName := fmt.Sprintf("%s-%s", f.Namespace.Name, "docker-config-example")
  227. dockerconfig := `{"auths":{"https://index.docker.io/v1/": {"auth": "c3R...zE2"}}}`
  228. cloudSecretValue := fmt.Sprintf(`{"dockerconfig": %s}`, dockerconfig)
  229. tc.Secrets = map[string]string{
  230. cloudSecretName: cloudSecretValue,
  231. }
  232. tc.ExpectedSecret = &v1.Secret{
  233. Type: v1.SecretTypeOpaque,
  234. Data: map[string][]byte{
  235. ".dockerconfigjson": []byte(dockerconfig),
  236. },
  237. }
  238. tc.ExternalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{
  239. {
  240. SecretKey: "mysecret",
  241. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  242. Key: cloudSecretName,
  243. Property: "dockerconfig",
  244. },
  245. },
  246. }
  247. tc.ExternalSecret.Spec.Target.Template = &esv1alpha1.ExternalSecretTemplate{
  248. Data: map[string]string{
  249. ".dockerconfigjson": "{{ .mysecret | toString }}",
  250. },
  251. }
  252. }
  253. }
  254. // This case creates a secret with a Docker json configuration value.
  255. // The values from the nested data are extracted using gjson.
  256. // Need to have a key holding dockerconfig to be supported by vault.
  257. func DataPropertyDockerconfigJSON(f *framework.Framework) (string, func(*framework.TestCase)) {
  258. return "[common] should sync docker configurated json secrets with template", func(tc *framework.TestCase) {
  259. cloudSecretName := fmt.Sprintf("%s-%s", f.Namespace.Name, "docker-config-example")
  260. dockerconfigString := `"{\"auths\":{\"https://index.docker.io/v1/\": {\"auth\": \"c3R...zE2\"}}}"`
  261. dockerconfig := `{"auths":{"https://index.docker.io/v1/": {"auth": "c3R...zE2"}}}`
  262. cloudSecretValue := fmt.Sprintf(`{"dockerconfig": %s}`, dockerconfigString)
  263. tc.Secrets = map[string]string{
  264. cloudSecretName: cloudSecretValue,
  265. }
  266. tc.ExpectedSecret = &v1.Secret{
  267. Type: v1.SecretTypeDockerConfigJson,
  268. Data: map[string][]byte{
  269. ".dockerconfigjson": []byte(dockerconfig),
  270. },
  271. }
  272. tc.ExternalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{
  273. {
  274. SecretKey: "mysecret",
  275. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  276. Key: cloudSecretName,
  277. Property: "dockerconfig",
  278. },
  279. },
  280. }
  281. tc.ExternalSecret.Spec.Target.Template = &esv1alpha1.ExternalSecretTemplate{
  282. Type: v1.SecretTypeDockerConfigJson,
  283. Data: map[string]string{
  284. ".dockerconfigjson": "{{ .mysecret | toString }}",
  285. },
  286. }
  287. }
  288. }
  289. // This case adds an ssh private key secret and sybcs it.
  290. // Not supported by: vault. Json parsing error.
  291. func SSHKeySync(f *framework.Framework) (string, func(*framework.TestCase)) {
  292. return "[common] should sync ssh key secret", func(tc *framework.TestCase) {
  293. sshSecretName := fmt.Sprintf("%s-%s", f.Namespace.Name, "ssh-priv-key-example")
  294. sshSecretValue := `EY2NNWddRADTFdNvEojrCwo+DUxy6va2JltQAbxmhyvSZsL1eYsutunsKEwonGSru0Zd+m
  295. z5DHJOOQdHEsH3AAAACmFub3RoZXJvbmU=
  296. -----END OPENSSH PRIVATE KEY-----`
  297. tc.Secrets = map[string]string{
  298. sshSecretName: sshSecretValue,
  299. }
  300. tc.ExpectedSecret = &v1.Secret{
  301. Type: v1.SecretTypeOpaque,
  302. Data: map[string][]byte{
  303. "ssh-privatekey": []byte(sshSecretValue),
  304. },
  305. }
  306. tc.ExternalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{
  307. {
  308. SecretKey: "mysecret",
  309. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  310. Key: sshSecretName,
  311. },
  312. },
  313. }
  314. tc.ExternalSecret.Spec.Target.Template = &esv1alpha1.ExternalSecretTemplate{
  315. Data: map[string]string{
  316. "ssh-privatekey": "{{ .mysecret | toString }}",
  317. },
  318. }
  319. }
  320. }
  321. // This case adds an ssh private key secret and syncs it.
  322. // Supported by vault. But does not work with any form of line breaks as standard ssh key.
  323. func SSHKeySyncDataProperty(f *framework.Framework) (string, func(*framework.TestCase)) {
  324. return "[common] should sync ssh key with provider.", func(tc *framework.TestCase) {
  325. cloudSecretName := fmt.Sprintf("%s-%s", f.Namespace.Name, "docker-config-example")
  326. SSHKey := "EY2NNWddRADTFdNvEojrCwo+DUxy6va2JltQAbxmhyvSZsL1eYsutunsKEwonGSru0Zd+m z5DHJOOQdHEsH3AAAACmFub3RoZXJvbmU= -----END OPENSSH PRIVATE KEY-----"
  327. cloudSecretValue := fmt.Sprintf(`{"ssh-auth": "%s"}`, SSHKey)
  328. tc.Secrets = map[string]string{
  329. cloudSecretName: cloudSecretValue,
  330. }
  331. tc.ExpectedSecret = &v1.Secret{
  332. Type: v1.SecretTypeSSHAuth,
  333. Data: map[string][]byte{
  334. "ssh-privatekey": []byte(SSHKey),
  335. },
  336. }
  337. tc.ExternalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{
  338. {
  339. SecretKey: "mysecret",
  340. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  341. Key: cloudSecretName,
  342. Property: "ssh-auth",
  343. },
  344. },
  345. }
  346. tc.ExternalSecret.Spec.Target.Template = &esv1alpha1.ExternalSecretTemplate{
  347. Type: v1.SecretTypeSSHAuth,
  348. Data: map[string]string{
  349. "ssh-privatekey": "{{ .mysecret | toString }}",
  350. },
  351. }
  352. }
  353. }