vault_test.go 4.7 KB

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