vault_test.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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 vaultdynamic
  13. import (
  14. "context"
  15. "errors"
  16. "testing"
  17. "github.com/google/go-cmp/cmp"
  18. corev1 "k8s.io/api/core/v1"
  19. apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
  20. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  21. typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
  22. kclient "sigs.k8s.io/controller-runtime/pkg/client"
  23. clientfake "sigs.k8s.io/controller-runtime/pkg/client/fake"
  24. utilfake "github.com/external-secrets/external-secrets/pkg/provider/util/fake"
  25. provider "github.com/external-secrets/external-secrets/pkg/provider/vault"
  26. "github.com/external-secrets/external-secrets/pkg/provider/vault/fake"
  27. )
  28. type args struct {
  29. jsonSpec *apiextensions.JSON
  30. kube kclient.Client
  31. corev1 typedcorev1.CoreV1Interface
  32. }
  33. type want struct {
  34. val map[string][]byte
  35. err error
  36. }
  37. type testCase struct {
  38. reason string
  39. args args
  40. want want
  41. }
  42. func TestVaultDynamicSecretGenerator(t *testing.T) {
  43. cases := map[string]testCase{
  44. "NilSpec": {
  45. reason: "Raise an error with empty spec.",
  46. args: args{
  47. jsonSpec: nil,
  48. },
  49. want: want{
  50. err: errors.New("no config spec provided"),
  51. },
  52. },
  53. "InvalidSpec": {
  54. reason: "Raise an error with invalid spec.",
  55. args: args{
  56. jsonSpec: &apiextensions.JSON{
  57. Raw: []byte(``),
  58. },
  59. },
  60. want: want{
  61. err: errors.New("no Vault provider config in spec"),
  62. },
  63. },
  64. "MissingRoleName": {
  65. reason: "Raise error if incomplete k8s auth config is provided.",
  66. args: args{
  67. corev1: utilfake.NewCreateTokenMock().WithToken("ok"),
  68. jsonSpec: &apiextensions.JSON{
  69. Raw: []byte(`apiVersion: generators.external-secrets.io/v1alpha1
  70. kind: VaultDynamicSecret
  71. spec:
  72. provider:
  73. auth:
  74. kubernetes:
  75. serviceAccountRef:
  76. name: "testing"
  77. method: GET
  78. path: "github/token/example"`),
  79. },
  80. kube: clientfake.NewClientBuilder().Build(),
  81. },
  82. want: want{
  83. err: errors.New("unable to setup Vault client: no role name was provided"),
  84. },
  85. },
  86. "EmptyVaultResponse": {
  87. reason: "Fail on empty response from Vault.",
  88. args: args{
  89. corev1: utilfake.NewCreateTokenMock().WithToken("ok"),
  90. jsonSpec: &apiextensions.JSON{
  91. Raw: []byte(`apiVersion: generators.external-secrets.io/v1alpha1
  92. kind: VaultDynamicSecret
  93. spec:
  94. provider:
  95. auth:
  96. kubernetes:
  97. role: test
  98. serviceAccountRef:
  99. name: "testing"
  100. method: GET
  101. path: "github/token/example"`),
  102. },
  103. kube: clientfake.NewClientBuilder().WithObjects(&corev1.ServiceAccount{
  104. ObjectMeta: metav1.ObjectMeta{
  105. Name: "testing",
  106. Namespace: "testing",
  107. },
  108. Secrets: []corev1.ObjectReference{
  109. {
  110. Name: "test",
  111. },
  112. },
  113. }).Build(),
  114. },
  115. want: want{
  116. err: errors.New("unable to get dynamic secret: empty response from Vault"),
  117. },
  118. },
  119. "EmptyVaultPOST": {
  120. reason: "Fail on empty response from Vault.",
  121. args: args{
  122. corev1: utilfake.NewCreateTokenMock().WithToken("ok"),
  123. jsonSpec: &apiextensions.JSON{
  124. Raw: []byte(`apiVersion: generators.external-secrets.io/v1alpha1
  125. kind: VaultDynamicSecret
  126. spec:
  127. provider:
  128. auth:
  129. kubernetes:
  130. role: test
  131. serviceAccountRef:
  132. name: "testing"
  133. method: POST
  134. parameters:
  135. foo: "bar"
  136. path: "github/token/example"`),
  137. },
  138. kube: clientfake.NewClientBuilder().WithObjects(&corev1.ServiceAccount{
  139. ObjectMeta: metav1.ObjectMeta{
  140. Name: "testing",
  141. Namespace: "testing",
  142. },
  143. Secrets: []corev1.ObjectReference{
  144. {
  145. Name: "test",
  146. },
  147. },
  148. }).Build(),
  149. },
  150. want: want{
  151. err: errors.New("unable to get dynamic secret: empty response from Vault"),
  152. },
  153. },
  154. }
  155. for name, tc := range cases {
  156. t.Run(name, func(t *testing.T) {
  157. c := &provider.Provider{NewVaultClient: fake.ClientWithLoginMock}
  158. gen := &Generator{}
  159. val, err := gen.generate(context.Background(), c, tc.args.jsonSpec, tc.args.kube, tc.args.corev1, "testing")
  160. if diff := cmp.Diff(tc.want.err.Error(), err.Error()); diff != "" {
  161. t.Errorf("\n%s\nvault.GetSecret(...): -want error, +got error:\n%s", tc.reason, diff)
  162. }
  163. if diff := cmp.Diff(tc.want.val, val); diff != "" {
  164. t.Errorf("\n%s\nvault.GetSecret(...): -want val, +got val:\n%s", tc.reason, diff)
  165. }
  166. })
  167. }
  168. }