| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- /*
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impliec.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package doppler
- import (
- "context"
- "encoding/json"
- "fmt"
- "net/url"
- "strings"
- "time"
- corev1 "k8s.io/api/core/v1"
- kclient "sigs.k8s.io/controller-runtime/pkg/client"
- esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
- "github.com/external-secrets/external-secrets/pkg/find"
- dClient "github.com/external-secrets/external-secrets/pkg/provider/doppler/client"
- "github.com/external-secrets/external-secrets/pkg/utils"
- "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
- )
- const (
- customBaseURLEnvVar = "DOPPLER_BASE_URL"
- verifyTLSOverrideEnvVar = "DOPPLER_VERIFY_TLS"
- errGetSecret = "could not get secret %s: %s"
- errGetSecrets = "could not get secrets %s"
- errUnmarshalSecretMap = "unable to unmarshal secret %s: %w"
- secretsDownloadFileKey = "DOPPLER_SECRETS_FILE"
- errDopplerTokenSecretName = "missing auth.secretRef.dopplerToken.name"
- errInvalidClusterStoreMissingDopplerTokenNamespace = "missing auth.secretRef.dopplerToken.namespace"
- )
- type Client struct {
- doppler SecretsClientInterface
- dopplerToken string
- project string
- config string
- nameTransformer string
- format string
- kube kclient.Client
- store *esv1beta1.DopplerProvider
- namespace string
- storeKind string
- }
- // SecretsClientInterface defines the required Doppler Client methods.
- type SecretsClientInterface interface {
- BaseURL() *url.URL
- Authenticate() error
- GetSecret(request dClient.SecretRequest) (*dClient.SecretResponse, error)
- GetSecrets(request dClient.SecretsRequest) (*dClient.SecretsResponse, error)
- }
- func (c *Client) setAuth(ctx context.Context) error {
- token, err := resolvers.SecretKeyRef(
- ctx,
- c.kube,
- c.storeKind,
- c.namespace,
- &c.store.Auth.SecretRef.DopplerToken)
- if err != nil {
- return err
- }
- c.dopplerToken = token
- return nil
- }
- func (c *Client) Validate() (esv1beta1.ValidationResult, error) {
- timeout := 15 * time.Second
- clientURL := c.doppler.BaseURL().String()
- if err := utils.NetworkValidate(clientURL, timeout); err != nil {
- return esv1beta1.ValidationResultError, err
- }
- if err := c.doppler.Authenticate(); err != nil {
- return esv1beta1.ValidationResultError, err
- }
- return esv1beta1.ValidationResultReady, nil
- }
- func (c *Client) DeleteSecret(_ context.Context, _ esv1beta1.PushSecretRemoteRef) error {
- return fmt.Errorf("not implemented")
- }
- func (c *Client) PushSecret(_ context.Context, _ *corev1.Secret, _ esv1beta1.PushSecretData) error {
- return fmt.Errorf("not implemented")
- }
- func (c *Client) GetSecret(_ context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
- request := dClient.SecretRequest{
- Name: ref.Key,
- Project: c.project,
- Config: c.config,
- }
- secret, err := c.doppler.GetSecret(request)
- if err != nil {
- return nil, fmt.Errorf(errGetSecret, ref.Key, err)
- }
- return []byte(secret.Value), nil
- }
- func (c *Client) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
- data, err := c.GetSecret(ctx, ref)
- if err != nil {
- return nil, err
- }
- kv := make(map[string]json.RawMessage)
- err = json.Unmarshal(data, &kv)
- if err != nil {
- return nil, fmt.Errorf(errUnmarshalSecretMap, ref.Key, err)
- }
- secretData := make(map[string][]byte)
- for k, v := range kv {
- var strVal string
- err = json.Unmarshal(v, &strVal)
- if err == nil {
- secretData[k] = []byte(strVal)
- } else {
- secretData[k] = v
- }
- }
- return secretData, nil
- }
- func (c *Client) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
- secrets, err := c.getSecrets(ctx)
- selected := map[string][]byte{}
- if err != nil {
- return nil, err
- }
- if ref.Name == nil && ref.Path == nil {
- return secrets, nil
- }
- var matcher *find.Matcher
- if ref.Name != nil {
- m, err := find.New(*ref.Name)
- if err != nil {
- return nil, err
- }
- matcher = m
- }
- for key, value := range secrets {
- if (matcher != nil && !matcher.MatchName(key)) || (ref.Path != nil && !strings.HasPrefix(key, *ref.Path)) {
- continue
- }
- selected[key] = value
- }
- return selected, nil
- }
- func (c *Client) Close(_ context.Context) error {
- return nil
- }
- func (c *Client) getSecrets(_ context.Context) (map[string][]byte, error) {
- request := dClient.SecretsRequest{
- Project: c.project,
- Config: c.config,
- NameTransformer: c.nameTransformer,
- Format: c.format,
- }
- response, err := c.doppler.GetSecrets(request)
- if err != nil {
- return nil, fmt.Errorf(errGetSecrets, err)
- }
- if c.format != "" {
- return map[string][]byte{
- secretsDownloadFileKey: response.Body,
- }, nil
- }
- return externalSecretsFormat(response.Secrets), nil
- }
- func externalSecretsFormat(secrets dClient.Secrets) map[string][]byte {
- converted := make(map[string][]byte, len(secrets))
- for key, value := range secrets {
- converted[key] = []byte(value)
- }
- return converted
- }
|