secretsmanager.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  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 aws
  13. import (
  14. "context"
  15. "fmt"
  16. // nolint
  17. . "github.com/onsi/ginkgo"
  18. // nolint
  19. . "github.com/onsi/gomega"
  20. v1 "k8s.io/api/core/v1"
  21. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  22. esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
  23. esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
  24. "github.com/external-secrets/external-secrets/e2e/framework"
  25. )
  26. const (
  27. targetSecret = "target-secret"
  28. )
  29. var _ = Describe("[aws] ", func() {
  30. f := framework.New("eso-aws")
  31. var secretStore *esv1alpha1.SecretStore
  32. localstackURL := "http://localstack.default"
  33. BeforeEach(func() {
  34. By("creating an secret store for localstack")
  35. awsCreds := &v1.Secret{
  36. ObjectMeta: metav1.ObjectMeta{
  37. Name: f.Namespace.Name,
  38. Namespace: f.Namespace.Name,
  39. },
  40. StringData: map[string]string{
  41. "kid": "foobar",
  42. "sak": "foobar",
  43. },
  44. }
  45. err := f.CRClient.Create(context.Background(), awsCreds)
  46. Expect(err).ToNot(HaveOccurred())
  47. secretStore = &esv1alpha1.SecretStore{
  48. ObjectMeta: metav1.ObjectMeta{
  49. Name: f.Namespace.Name,
  50. Namespace: f.Namespace.Name,
  51. },
  52. Spec: esv1alpha1.SecretStoreSpec{
  53. Provider: &esv1alpha1.SecretStoreProvider{
  54. AWS: &esv1alpha1.AWSProvider{
  55. Service: esv1alpha1.AWSServiceSecretsManager,
  56. Region: "us-east-1",
  57. Auth: esv1alpha1.AWSAuth{
  58. SecretRef: &esv1alpha1.AWSAuthSecretRef{
  59. AccessKeyID: esmeta.SecretKeySelector{
  60. Name: f.Namespace.Name,
  61. Key: "kid",
  62. },
  63. SecretAccessKey: esmeta.SecretKeySelector{
  64. Name: f.Namespace.Name,
  65. Key: "sak",
  66. },
  67. },
  68. },
  69. },
  70. },
  71. },
  72. }
  73. err = f.CRClient.Create(context.Background(), secretStore)
  74. Expect(err).ToNot(HaveOccurred())
  75. })
  76. It("should sync multiple secrets", func() {
  77. By("creating a AWS SM Secret")
  78. secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one")
  79. secretKey2 := fmt.Sprintf("%s-%s", f.Namespace.Name, "other")
  80. secretValue := "bar"
  81. err := CreateAWSSecretsManagerSecret(
  82. localstackURL,
  83. secretKey1, secretValue)
  84. Expect(err).ToNot(HaveOccurred())
  85. err = CreateAWSSecretsManagerSecret(
  86. localstackURL,
  87. secretKey2, secretValue)
  88. Expect(err).ToNot(HaveOccurred())
  89. err = f.CRClient.Create(context.Background(), &esv1alpha1.ExternalSecret{
  90. ObjectMeta: metav1.ObjectMeta{
  91. Name: "simple-sync",
  92. Namespace: f.Namespace.Name,
  93. },
  94. Spec: esv1alpha1.ExternalSecretSpec{
  95. SecretStoreRef: esv1alpha1.SecretStoreRef{
  96. Name: f.Namespace.Name,
  97. },
  98. Target: esv1alpha1.ExternalSecretTarget{
  99. Name: targetSecret,
  100. },
  101. Data: []esv1alpha1.ExternalSecretData{
  102. {
  103. SecretKey: secretKey1,
  104. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  105. Key: secretKey1,
  106. },
  107. },
  108. {
  109. SecretKey: secretKey2,
  110. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  111. Key: secretKey2,
  112. },
  113. },
  114. },
  115. },
  116. })
  117. Expect(err).ToNot(HaveOccurred())
  118. _, err = f.WaitForSecretValue(f.Namespace.Name, targetSecret, map[string][]byte{
  119. secretKey1: []byte(secretValue),
  120. secretKey2: []byte(secretValue),
  121. })
  122. Expect(err).ToNot(HaveOccurred())
  123. })
  124. It("should sync secrets with dataFrom", func() {
  125. By("creating a AWS SM Secret")
  126. secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one")
  127. targetSecretKey1 := "name"
  128. targetSecretValue1 := "great-name"
  129. targetSecretKey2 := "surname"
  130. targetSecretValue2 := "great-surname"
  131. secretValue := fmt.Sprintf("{ \"%s\": \"%s\", \"%s\": \"%s\" }", targetSecretKey1, targetSecretValue1, targetSecretKey2, targetSecretValue2)
  132. err := CreateAWSSecretsManagerSecret(
  133. localstackURL,
  134. secretKey1, secretValue)
  135. Expect(err).ToNot(HaveOccurred())
  136. err = f.CRClient.Create(context.Background(), &esv1alpha1.ExternalSecret{
  137. ObjectMeta: metav1.ObjectMeta{
  138. Name: "datafrom-sync",
  139. Namespace: f.Namespace.Name,
  140. },
  141. Spec: esv1alpha1.ExternalSecretSpec{
  142. SecretStoreRef: esv1alpha1.SecretStoreRef{
  143. Name: f.Namespace.Name,
  144. },
  145. Target: esv1alpha1.ExternalSecretTarget{
  146. Name: targetSecret,
  147. },
  148. DataFrom: []esv1alpha1.ExternalSecretDataRemoteRef{
  149. {
  150. Key: secretKey1,
  151. },
  152. },
  153. },
  154. })
  155. Expect(err).ToNot(HaveOccurred())
  156. _, err = f.WaitForSecretValue(f.Namespace.Name, targetSecret, map[string][]byte{
  157. targetSecretKey1: []byte(targetSecretValue1),
  158. targetSecretKey2: []byte(targetSecretValue2),
  159. })
  160. Expect(err).ToNot(HaveOccurred())
  161. })
  162. It("should sync secrets and get inner keys", func() {
  163. By("creating a AWS SM Secret")
  164. secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one")
  165. targetSecretKey1 := "firstname"
  166. targetSecretValue1 := "Tom"
  167. targetSecretKey2 := "first_friend"
  168. targetSecretValue2 := "Roger"
  169. secretValue := fmt.Sprintf(
  170. `{
  171. "name": {"first": "%s", "last": "Anderson"},
  172. "friends":
  173. [
  174. {"first": "Dale", "last": "Murphy"},
  175. {"first": "%s", "last": "Craig"},
  176. {"first": "Jane", "last": "Murphy"}
  177. ]
  178. }`, targetSecretValue1, targetSecretValue2)
  179. err := CreateAWSSecretsManagerSecret(
  180. localstackURL,
  181. secretKey1, secretValue)
  182. Expect(err).ToNot(HaveOccurred())
  183. err = f.CRClient.Create(context.Background(), &esv1alpha1.ExternalSecret{
  184. ObjectMeta: metav1.ObjectMeta{
  185. Name: "datafrom-sync",
  186. Namespace: f.Namespace.Name,
  187. },
  188. Spec: esv1alpha1.ExternalSecretSpec{
  189. SecretStoreRef: esv1alpha1.SecretStoreRef{
  190. Name: f.Namespace.Name,
  191. },
  192. Target: esv1alpha1.ExternalSecretTarget{
  193. Name: targetSecret,
  194. },
  195. Data: []esv1alpha1.ExternalSecretData{
  196. {
  197. SecretKey: targetSecretKey1,
  198. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  199. Key: secretKey1,
  200. Property: "name.first",
  201. },
  202. },
  203. {
  204. SecretKey: targetSecretKey2,
  205. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  206. Key: secretKey1,
  207. Property: "friends.1.first",
  208. },
  209. },
  210. },
  211. },
  212. })
  213. Expect(err).ToNot(HaveOccurred())
  214. _, err = f.WaitForSecretValue(f.Namespace.Name, targetSecret, map[string][]byte{
  215. targetSecretKey1: []byte(targetSecretValue1),
  216. targetSecretKey2: []byte(targetSecretValue2),
  217. })
  218. Expect(err).ToNot(HaveOccurred())
  219. })
  220. It("should sync secrets with cluster secret store", func() {
  221. By("creating a AWS SM Secret")
  222. clusterStoreName := fmt.Sprintf("cluster-%s", f.Namespace.Name)
  223. targetSecretKey := "FOOB"
  224. secretKey := fmt.Sprintf("%s-%s", f.Namespace.Name, "one")
  225. secretValue := "MYVAL"
  226. err := CreateAWSSecretsManagerSecret(
  227. localstackURL,
  228. secretKey, secretValue)
  229. Expect(err).ToNot(HaveOccurred())
  230. css := &esv1alpha1.ClusterSecretStore{
  231. ObjectMeta: metav1.ObjectMeta{
  232. Name: clusterStoreName,
  233. },
  234. Spec: esv1alpha1.SecretStoreSpec{
  235. Provider: &esv1alpha1.SecretStoreProvider{
  236. AWS: &esv1alpha1.AWSProvider{
  237. Service: esv1alpha1.AWSServiceSecretsManager,
  238. Region: "us-east-1",
  239. Auth: esv1alpha1.AWSAuth{
  240. SecretRef: &esv1alpha1.AWSAuthSecretRef{
  241. AccessKeyID: esmeta.SecretKeySelector{
  242. Name: f.Namespace.Name,
  243. Namespace: &f.Namespace.Name,
  244. Key: "kid",
  245. },
  246. SecretAccessKey: esmeta.SecretKeySelector{
  247. Name: f.Namespace.Name,
  248. Namespace: &f.Namespace.Name,
  249. Key: "sak",
  250. },
  251. },
  252. },
  253. },
  254. },
  255. },
  256. }
  257. err = f.CRClient.Create(context.Background(), css)
  258. Expect(err).ToNot(HaveOccurred())
  259. defer func() {
  260. err = f.CRClient.Delete(context.Background(), css)
  261. Expect(err).ToNot(HaveOccurred())
  262. }()
  263. err = f.CRClient.Create(context.Background(), &esv1alpha1.ExternalSecret{
  264. ObjectMeta: metav1.ObjectMeta{
  265. Name: "datafrom-sync",
  266. Namespace: f.Namespace.Name,
  267. },
  268. Spec: esv1alpha1.ExternalSecretSpec{
  269. SecretStoreRef: esv1alpha1.SecretStoreRef{
  270. Name: clusterStoreName,
  271. Kind: esv1alpha1.ClusterSecretStoreKind,
  272. },
  273. Target: esv1alpha1.ExternalSecretTarget{
  274. Name: targetSecret,
  275. },
  276. Data: []esv1alpha1.ExternalSecretData{
  277. {
  278. SecretKey: targetSecretKey,
  279. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  280. Key: secretKey,
  281. },
  282. },
  283. },
  284. },
  285. })
  286. Expect(err).ToNot(HaveOccurred())
  287. _, err = f.WaitForSecretValue(f.Namespace.Name, targetSecret, map[string][]byte{
  288. targetSecretKey: []byte(secretValue),
  289. })
  290. Expect(err).ToNot(HaveOccurred())
  291. })
  292. It("should use jwt auth tokens", func() {
  293. By("creating a AWS SM Secret")
  294. clusterStoreName := fmt.Sprintf("cluster-jwt-%s", f.Namespace.Name)
  295. targetSecretKey := "FOOB"
  296. saName := "my-sa"
  297. secretKey := fmt.Sprintf("%s-%s", f.Namespace.Name, "jwt-token")
  298. secretValue := "MYVAL"
  299. err := CreateAWSSecretsManagerSecret(
  300. localstackURL,
  301. secretKey, secretValue)
  302. Expect(err).ToNot(HaveOccurred())
  303. err = f.CRClient.Create(context.Background(), &v1.ServiceAccount{
  304. ObjectMeta: metav1.ObjectMeta{
  305. Name: saName,
  306. Namespace: f.Namespace.Name,
  307. Annotations: map[string]string{
  308. "eks.amazonaws.com/role-arn": "arn:aws:iam::account:role/my-example-role",
  309. },
  310. },
  311. })
  312. Expect(err).ToNot(HaveOccurred())
  313. err = f.CRClient.Create(context.Background(), &esv1alpha1.ClusterSecretStore{
  314. ObjectMeta: metav1.ObjectMeta{
  315. Name: clusterStoreName,
  316. },
  317. Spec: esv1alpha1.SecretStoreSpec{
  318. Provider: &esv1alpha1.SecretStoreProvider{
  319. AWS: &esv1alpha1.AWSProvider{
  320. Service: esv1alpha1.AWSServiceSecretsManager,
  321. Region: "us-east-1",
  322. Auth: esv1alpha1.AWSAuth{
  323. JWTAuth: &esv1alpha1.AWSJWTAuth{
  324. ServiceAccountRef: &esmeta.ServiceAccountSelector{
  325. Name: saName,
  326. Namespace: &f.Namespace.Name,
  327. },
  328. },
  329. },
  330. },
  331. },
  332. },
  333. })
  334. Expect(err).ToNot(HaveOccurred())
  335. err = f.CRClient.Create(context.Background(), &esv1alpha1.ExternalSecret{
  336. ObjectMeta: metav1.ObjectMeta{
  337. Name: "jwt-sync",
  338. Namespace: f.Namespace.Name,
  339. },
  340. Spec: esv1alpha1.ExternalSecretSpec{
  341. SecretStoreRef: esv1alpha1.SecretStoreRef{
  342. Name: clusterStoreName,
  343. Kind: esv1alpha1.ClusterSecretStoreKind,
  344. },
  345. Target: esv1alpha1.ExternalSecretTarget{
  346. Name: targetSecret,
  347. },
  348. Data: []esv1alpha1.ExternalSecretData{
  349. {
  350. SecretKey: targetSecretKey,
  351. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  352. Key: secretKey,
  353. },
  354. },
  355. },
  356. },
  357. })
  358. Expect(err).ToNot(HaveOccurred())
  359. _, err = f.WaitForSecretValue(f.Namespace.Name, targetSecret, map[string][]byte{
  360. targetSecretKey: []byte(secretValue),
  361. })
  362. Expect(err).ToNot(HaveOccurred())
  363. })
  364. })