provider.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. // Package conjur provides a Conjur provider for External Secrets.
  2. /*
  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. http://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 conjur
  14. import (
  15. "context"
  16. "encoding/json"
  17. "fmt"
  18. "strings"
  19. "github.com/cyberark/conjur-api-go/conjurapi"
  20. "github.com/cyberark/conjur-api-go/conjurapi/authn"
  21. corev1 "k8s.io/api/core/v1"
  22. apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
  23. "k8s.io/client-go/kubernetes"
  24. typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
  25. "sigs.k8s.io/controller-runtime/pkg/client"
  26. ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
  27. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  28. esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
  29. "github.com/external-secrets/external-secrets/pkg/provider/conjur/util"
  30. "github.com/external-secrets/external-secrets/pkg/utils"
  31. )
  32. var (
  33. errConjurClient = "cannot setup new Conjur client: %w"
  34. errBadCertBundle = "caBundle failed to base64 decode: %w"
  35. errBadServiceUser = "could not get Auth.Apikey.UserRef: %w"
  36. errBadServiceAPIKey = "could not get Auth.Apikey.ApiKeyRef: %w"
  37. errGetKubeSATokenRequest = "cannot request Kubernetes service account token for service account %q: %w"
  38. errUnableToFetchCAProviderCM = "unable to fetch Server.CAProvider ConfigMap: %w"
  39. errUnableToFetchCAProviderSecret = "unable to fetch Server.CAProvider Secret: %w"
  40. )
  41. // Client is a provider for Conjur.
  42. type Client struct {
  43. StoreKind string
  44. kube client.Client
  45. store esv1beta1.GenericStore
  46. namespace string
  47. corev1 typedcorev1.CoreV1Interface
  48. clientAPI SecretsClientFactory
  49. client SecretsClient
  50. }
  51. type Provider struct {
  52. NewConjurProvider func(context context.Context, store esv1beta1.GenericStore, kube client.Client, namespace string, corev1 typedcorev1.CoreV1Interface, clientApi SecretsClientFactory) (esv1beta1.SecretsClient, error)
  53. }
  54. // NewClient creates a new Conjur client.
  55. func (c *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore, kube client.Client, namespace string) (esv1beta1.SecretsClient, error) {
  56. // controller-runtime/client does not support TokenRequest or other subresource APIs
  57. // so we need to construct our own client and use it to create a TokenRequest
  58. restCfg, err := ctrlcfg.GetConfig()
  59. if err != nil {
  60. return nil, err
  61. }
  62. clientset, err := kubernetes.NewForConfig(restCfg)
  63. if err != nil {
  64. return nil, err
  65. }
  66. return c.NewConjurProvider(ctx, store, kube, namespace, clientset.CoreV1(), &ClientAPIImpl{})
  67. }
  68. func newConjurProvider(_ context.Context, store esv1beta1.GenericStore, kube client.Client, namespace string, corev1 typedcorev1.CoreV1Interface, clientAPI SecretsClientFactory) (esv1beta1.SecretsClient, error) {
  69. return &Client{
  70. StoreKind: store.GetObjectKind().GroupVersionKind().Kind,
  71. store: store,
  72. kube: kube,
  73. namespace: namespace,
  74. corev1: corev1,
  75. clientAPI: clientAPI,
  76. }, nil
  77. }
  78. func (p *Client) GetConjurClient(ctx context.Context) (SecretsClient, error) {
  79. // if the client is initialized already, return it
  80. if p.client != nil {
  81. return p.client, nil
  82. }
  83. prov, err := util.GetConjurProvider(p.store)
  84. if err != nil {
  85. return nil, err
  86. }
  87. cert, getCertErr := p.getCA(ctx, prov)
  88. if getCertErr != nil {
  89. return nil, getCertErr
  90. }
  91. config := conjurapi.Config{
  92. ApplianceURL: prov.URL,
  93. SSLCert: cert,
  94. }
  95. if prov.Auth.Apikey != nil {
  96. config.Account = prov.Auth.Apikey.Account
  97. conjUser, secErr := p.secretKeyRef(ctx, prov.Auth.Apikey.UserRef)
  98. if secErr != nil {
  99. return nil, fmt.Errorf(errBadServiceUser, secErr)
  100. }
  101. conjAPIKey, secErr := p.secretKeyRef(ctx, prov.Auth.Apikey.APIKeyRef)
  102. if secErr != nil {
  103. return nil, fmt.Errorf(errBadServiceAPIKey, secErr)
  104. }
  105. conjur, newClientFromKeyError := p.clientAPI.NewClientFromKey(config,
  106. authn.LoginPair{
  107. Login: conjUser,
  108. APIKey: conjAPIKey,
  109. },
  110. )
  111. if newClientFromKeyError != nil {
  112. return nil, fmt.Errorf(errConjurClient, newClientFromKeyError)
  113. }
  114. p.client = conjur
  115. return conjur, nil
  116. } else if prov.Auth.Jwt != nil {
  117. config.Account = prov.Auth.Jwt.Account
  118. conjur, clientFromJwtError := p.newClientFromJwt(ctx, config, prov.Auth.Jwt)
  119. if clientFromJwtError != nil {
  120. return nil, fmt.Errorf(errConjurClient, clientFromJwtError)
  121. }
  122. p.client = conjur
  123. return conjur, nil
  124. } else {
  125. // Should not happen because validate func should catch this
  126. return nil, fmt.Errorf("no authentication method provided")
  127. }
  128. }
  129. // GetAllSecrets returns all secrets from the provider.
  130. // NOT IMPLEMENTED.
  131. func (p *Client) GetAllSecrets(_ context.Context, _ esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
  132. // TO be implemented
  133. return nil, fmt.Errorf("GetAllSecrets not implemented")
  134. }
  135. // GetSecret returns a single secret from the provider.
  136. func (p *Client) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
  137. conjurClient, getConjurClientError := p.GetConjurClient(ctx)
  138. if getConjurClientError != nil {
  139. return nil, getConjurClientError
  140. }
  141. secretValue, err := conjurClient.RetrieveSecret(ref.Key)
  142. if err != nil {
  143. return nil, err
  144. }
  145. return secretValue, nil
  146. }
  147. // PushSecret will write a single secret into the provider.
  148. func (p *Client) PushSecret(_ context.Context, _ []byte, _ *apiextensionsv1.JSON, _ esv1beta1.PushRemoteRef) error {
  149. // NOT IMPLEMENTED
  150. return nil
  151. }
  152. func (p *Client) DeleteSecret(_ context.Context, _ esv1beta1.PushRemoteRef) error {
  153. // NOT IMPLEMENTED
  154. return nil
  155. }
  156. // GetSecretMap returns multiple k/v pairs from the provider.
  157. func (p *Client) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
  158. // Gets a secret as normal, expecting secret value to be a json object
  159. data, err := p.GetSecret(ctx, ref)
  160. if err != nil {
  161. return nil, fmt.Errorf("error getting secret %s: %w", ref.Key, err)
  162. }
  163. // Maps the json data to a string:string map
  164. kv := make(map[string]string)
  165. err = json.Unmarshal(data, &kv)
  166. if err != nil {
  167. return nil, fmt.Errorf("unable to unmarshal secret %s: %w", ref.Key, err)
  168. }
  169. // Converts values in K:V pairs into bytes, while leaving keys as strings
  170. secretData := make(map[string][]byte)
  171. for k, v := range kv {
  172. secretData[k] = []byte(v)
  173. }
  174. return secretData, nil
  175. }
  176. // Close closes the provider.
  177. func (p *Client) Close(_ context.Context) error {
  178. return nil
  179. }
  180. // Validate validates the provider.
  181. func (p *Client) Validate() (esv1beta1.ValidationResult, error) {
  182. return esv1beta1.ValidationResultReady, nil
  183. }
  184. // ValidateStore validates the store.
  185. func (c *Provider) ValidateStore(store esv1beta1.GenericStore) error {
  186. prov, err := util.GetConjurProvider(store)
  187. if err != nil {
  188. return err
  189. }
  190. if prov.URL == "" {
  191. return fmt.Errorf("conjur URL cannot be empty")
  192. }
  193. if prov.Auth.Apikey != nil {
  194. if prov.Auth.Apikey.Account == "" {
  195. return fmt.Errorf("missing Auth.ApiKey.Account")
  196. }
  197. if prov.Auth.Apikey.UserRef == nil {
  198. return fmt.Errorf("missing Auth.Apikey.UserRef")
  199. }
  200. if prov.Auth.Apikey.APIKeyRef == nil {
  201. return fmt.Errorf("missing Auth.Apikey.ApiKeyRef")
  202. }
  203. if err := utils.ValidateReferentSecretSelector(store, *prov.Auth.Apikey.UserRef); err != nil {
  204. return fmt.Errorf("invalid Auth.Apikey.UserRef: %w", err)
  205. }
  206. if err := utils.ValidateReferentSecretSelector(store, *prov.Auth.Apikey.APIKeyRef); err != nil {
  207. return fmt.Errorf("invalid Auth.Apikey.ApiKeyRef: %w", err)
  208. }
  209. }
  210. if prov.Auth.Jwt != nil {
  211. if prov.Auth.Jwt.Account == "" {
  212. return fmt.Errorf("missing Auth.Jwt.Account")
  213. }
  214. if prov.Auth.Jwt.ServiceID == "" {
  215. return fmt.Errorf("missing Auth.Jwt.ServiceID")
  216. }
  217. if prov.Auth.Jwt.ServiceAccountRef == nil && prov.Auth.Jwt.SecretRef == nil {
  218. return fmt.Errorf("must specify Auth.Jwt.SecretRef or Auth.Jwt.ServiceAccountRef")
  219. }
  220. if prov.Auth.Jwt.SecretRef != nil {
  221. if err := utils.ValidateReferentSecretSelector(store, *prov.Auth.Jwt.SecretRef); err != nil {
  222. return fmt.Errorf("invalid Auth.Jwt.SecretRef: %w", err)
  223. }
  224. }
  225. if prov.Auth.Jwt.ServiceAccountRef != nil {
  226. if err := utils.ValidateReferentServiceAccountSelector(store, *prov.Auth.Jwt.ServiceAccountRef); err != nil {
  227. return fmt.Errorf("invalid Auth.Jwt.ServiceAccountRef: %w", err)
  228. }
  229. }
  230. }
  231. // At least one auth must be configured
  232. if prov.Auth.Apikey == nil && prov.Auth.Jwt == nil {
  233. return fmt.Errorf("missing Auth.* configuration")
  234. }
  235. return nil
  236. }
  237. // Capabilities returns the provider Capabilities (Read, Write, ReadWrite).
  238. func (c *Provider) Capabilities() esv1beta1.SecretStoreCapabilities {
  239. return esv1beta1.SecretStoreReadOnly
  240. }
  241. func (p *Client) secretKeyRef(ctx context.Context, secretRef *esmeta.SecretKeySelector) (string, error) {
  242. secret := &corev1.Secret{}
  243. ref := client.ObjectKey{
  244. Namespace: p.namespace,
  245. Name: secretRef.Name,
  246. }
  247. if (p.StoreKind == esv1beta1.ClusterSecretStoreKind) &&
  248. (secretRef.Namespace != nil) {
  249. ref.Namespace = *secretRef.Namespace
  250. }
  251. err := p.kube.Get(ctx, ref, secret)
  252. if err != nil {
  253. return "", err
  254. }
  255. keyBytes, ok := secret.Data[secretRef.Key]
  256. if !ok {
  257. return "", err
  258. }
  259. value := string(keyBytes)
  260. valueStr := strings.TrimSpace(value)
  261. return valueStr, nil
  262. }
  263. // configMapKeyRef returns the value of a key in a configmap.
  264. func (p *Client) configMapKeyRef(ctx context.Context, cmRef *esmeta.SecretKeySelector) (string, error) {
  265. configMap := &corev1.ConfigMap{}
  266. ref := client.ObjectKey{
  267. Namespace: p.namespace,
  268. Name: cmRef.Name,
  269. }
  270. if (p.StoreKind == esv1beta1.ClusterSecretStoreKind) &&
  271. (cmRef.Namespace != nil) {
  272. ref.Namespace = *cmRef.Namespace
  273. }
  274. err := p.kube.Get(ctx, ref, configMap)
  275. if err != nil {
  276. return "", err
  277. }
  278. keyBytes, ok := configMap.Data[cmRef.Key]
  279. if !ok {
  280. return "", err
  281. }
  282. valueStr := strings.TrimSpace(keyBytes)
  283. return valueStr, nil
  284. }
  285. // getCA try retrieve the CA bundle from the provider CABundle or from the CAProvider.
  286. func (p *Client) getCA(ctx context.Context, provider *esv1beta1.ConjurProvider) (string, error) {
  287. if provider.CAProvider != nil {
  288. var ca string
  289. var err error
  290. switch provider.CAProvider.Type {
  291. case esv1beta1.CAProviderTypeConfigMap:
  292. keySelector := esmeta.SecretKeySelector{
  293. Name: provider.CAProvider.Name,
  294. Namespace: provider.CAProvider.Namespace,
  295. Key: provider.CAProvider.Key,
  296. }
  297. ca, err = p.configMapKeyRef(ctx, &keySelector)
  298. if err != nil {
  299. return "", fmt.Errorf(errUnableToFetchCAProviderCM, err)
  300. }
  301. case esv1beta1.CAProviderTypeSecret:
  302. keySelector := esmeta.SecretKeySelector{
  303. Name: provider.CAProvider.Name,
  304. Namespace: provider.CAProvider.Namespace,
  305. Key: provider.CAProvider.Key,
  306. }
  307. ca, err = p.secretKeyRef(ctx, &keySelector)
  308. if err != nil {
  309. return "", fmt.Errorf(errUnableToFetchCAProviderSecret, err)
  310. }
  311. }
  312. return ca, nil
  313. }
  314. certBytes, decodeErr := utils.Decode(esv1beta1.ExternalSecretDecodeBase64, []byte(provider.CABundle))
  315. if decodeErr != nil {
  316. return "", fmt.Errorf(errBadCertBundle, decodeErr)
  317. }
  318. return string(certBytes), nil
  319. }
  320. func init() {
  321. esv1beta1.Register(&Provider{
  322. NewConjurProvider: newConjurProvider,
  323. }, &esv1beta1.SecretStoreProvider{
  324. Conjur: &esv1beta1.ConjurProvider{},
  325. })
  326. }