From 709db58d5b2b90e467ae7057e7d6ca212a63c0f0 Mon Sep 17 00:00:00 2001 From: Denis Policastro Date: Wed, 18 Jan 2023 17:08:23 -0300 Subject: [PATCH 01/62] Update aws-parameter-store.md (#1931) Signed-off-by: Denis Policastro Signed-off-by: Denis Policastro --- docs/provider/aws-parameter-store.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/provider/aws-parameter-store.md b/docs/provider/aws-parameter-store.md index 1414cc5a1dd..988aa78f99b 100644 --- a/docs/provider/aws-parameter-store.md +++ b/docs/provider/aws-parameter-store.md @@ -30,6 +30,7 @@ Create a IAM Policy to pin down access to secrets matching `dev-*`, for further { "Effect": "Allow", "Action": [ + "ssm:GetParameter", "ssm:GetParameterWithContext", "ssm:ListTagsForResourceWithContext", "ssm:DescribeParametersWithContext", From 769efdc391a1f9ca524f76199af190a6ef64317c Mon Sep 17 00:00:00 2001 From: Gustavo Fernandes de Carvalho Date: Thu, 19 Jan 2023 06:37:19 -0300 Subject: [PATCH 02/62] :sparkles: Feature/deletion policies (#1914) Signed-off-by: Gustavo Carvalho --- docs/introduction/stability-support.md | 36 +++++++++---------- pkg/provider/azure/keyvault/keyvault.go | 15 +++++++- pkg/provider/azure/keyvault/keyvault_test.go | 23 ++++++++++++ pkg/provider/gcp/secretmanager/client.go | 9 +++++ pkg/provider/gcp/secretmanager/client_test.go | 8 +++++ pkg/provider/kubernetes/client.go | 4 +++ pkg/provider/kubernetes/client_test.go | 27 +++++++++++++- 7 files changed, 102 insertions(+), 20 deletions(-) diff --git a/docs/introduction/stability-support.md b/docs/introduction/stability-support.md index 243a1163cfe..08a1a84cf85 100644 --- a/docs/introduction/stability-support.md +++ b/docs/introduction/stability-support.md @@ -44,24 +44,24 @@ The following table describes the stability level of each provider and who's res The following table show the support for features across different providers. -| Provider | find by name | find by tags | metadataPolicy Fetch | referent authentication | store validation | push secret | -|---------------------------|:------------:|:------------:| :------------------: | :---------------------: | :--------------: | :---------: | -| AWS Secrets Manager | x | x | | x | x | | -| AWS Parameter Store | x | x | | x | x | | -| Hashicorp Vault | x | x | | x | x | | -| GCP Secret Manager | x | x | | x | x | | -| Azure Keyvault | x | x | x | x | x | x | -| Kubernetes | x | x | | x | x | | -| IBM Cloud Secrets Manager | | | | | x | | -| Yandex Lockbox | | | | | x | | -| Gitlab Variables | x | x | | | x | | -| Alibaba Cloud KMS | | | | | x | | -| Oracle Vault | | | | | x | | -| Akeyless | | | | | x | | -| 1Password | x | | | | x | | -| Generic Webhook | | | | | | | -| senhasegura DSM | | | | | x | | -| Doppler | x | | | | x | | +| Provider | find by name | find by tags | metadataPolicy Fetch | referent authentication | store validation | push secret | DeletionPolicy Merge/Delete | +|---------------------------|:------------:|:------------:| :------------------: | :---------------------: | :--------------: | :---------: | :-------------------------: +| AWS Secrets Manager | x | x | | x | x | x | x | +| AWS Parameter Store | x | x | | x | x | x | x | +| Hashicorp Vault | x | x | | x | x | x | x | +| GCP Secret Manager | x | x | | x | x | x | x | +| Azure Keyvault | x | x | x | x | x | x | x | +| Kubernetes | x | x | | x | x | x | x | +| IBM Cloud Secrets Manager | | | | | x | | | +| Yandex Lockbox | | | | | x | | | +| Gitlab Variables | x | x | | | x | | | +| Alibaba Cloud KMS | | | | | x | | | +| Oracle Vault | | | | | x | | | +| Akeyless | | | | | x | | | +| 1Password | x | | | | x | | | +| Generic Webhook | | | | | | | | +| senhasegura DSM | | | | | x | | | +| Doppler | x | | | | x | | | ## Support Policy diff --git a/pkg/provider/azure/keyvault/keyvault.go b/pkg/provider/azure/keyvault/keyvault.go index d0aa7890191..30d08500e72 100644 --- a/pkg/provider/azure/keyvault/keyvault.go +++ b/pkg/provider/azure/keyvault/keyvault.go @@ -489,6 +489,7 @@ func (a *Azure) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecretF checkName := ref.Name != nil && len(ref.Name.RegExp) > 0 secretListIter, err := basicClient.GetSecretsComplete(context.Background(), *a.provider.VaultURL, nil) + err = parseError(err) if err != nil { return nil, err } @@ -502,6 +503,7 @@ func (a *Azure) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecretF } secretResp, err := basicClient.GetSecret(context.Background(), *a.provider.VaultURL, secretName, "") + err = parseError(err) if err != nil { return nil, err } @@ -568,6 +570,14 @@ func getProperty(secret, property, key string) ([]byte, error) { return []byte(res.String()), nil } +func parseError(err error) error { + aerr := autorest.DetailedError{} + if errors.As(err, &aerr) && aerr.StatusCode == 404 { + return esv1beta1.NoSecretError{} + } + return err +} + // Implements store.Client.GetSecret Interface. // Retrieves a secret/Key/Certificate/Tag with the secret name defined in ref.Name // The Object Type is defined as a prefix in the ref.Name , if no prefix is defined , we assume a secret is required. @@ -579,6 +589,7 @@ func (a *Azure) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataR // returns a SecretBundle with the secret value // https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault#SecretBundle secretResp, err := a.baseClient.GetSecret(context.Background(), *a.provider.VaultURL, secretName, ref.Version) + err = parseError(err) if err != nil { return nil, err } @@ -590,6 +601,7 @@ func (a *Azure) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataR // returns a CertBundle. We return CER contents of x509 certificate // see: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault#CertificateBundle certResp, err := a.baseClient.GetCertificate(context.Background(), *a.provider.VaultURL, secretName, ref.Version) + err = parseError(err) if err != nil { return nil, err } @@ -602,6 +614,7 @@ func (a *Azure) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataR // azure kv returns only public keys // see: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault#KeyBundle keyResp, err := a.baseClient.GetKey(context.Background(), *a.provider.VaultURL, secretName, ref.Version) + err = parseError(err) if err != nil { return nil, err } @@ -618,7 +631,7 @@ func (a *Azure) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataR func (a *Azure) getSecretTags(ref esv1beta1.ExternalSecretDataRemoteRef) (map[string]*string, error) { _, secretName := getObjType(ref) secretResp, err := a.baseClient.GetSecret(context.Background(), *a.provider.VaultURL, secretName, ref.Version) - + err = parseError(err) if err != nil { return nil, err } diff --git a/pkg/provider/azure/keyvault/keyvault_test.go b/pkg/provider/azure/keyvault/keyvault_test.go index 2ab00c8e33d..53452c50110 100644 --- a/pkg/provider/azure/keyvault/keyvault_test.go +++ b/pkg/provider/azure/keyvault/keyvault_test.go @@ -763,6 +763,26 @@ func TestAzureKeyVaultSecretManagerGetSecret(t *testing.T) { Value: &secretString, } } + // good case + secretNotFound := func(smtc *secretManagerTestCase) { + smtc.expectedSecret = "" + smtc.apiErr = autorest.DetailedError{StatusCode: 404} + smtc.expectError = esv1beta1.NoSecretError{}.Error() + } + + certNotFound := func(smtc *secretManagerTestCase) { + smtc.expectedSecret = "" + smtc.secretName = certName + smtc.apiErr = autorest.DetailedError{StatusCode: 404} + smtc.expectError = esv1beta1.NoSecretError{}.Error() + } + + keyNotFound := func(smtc *secretManagerTestCase) { + smtc.expectedSecret = "" + smtc.secretName = keyName + smtc.apiErr = autorest.DetailedError{StatusCode: 404} + smtc.expectError = esv1beta1.NoSecretError{}.Error() + } setSecretStringWithVersion := func(smtc *secretManagerTestCase) { smtc.expectedSecret = secretString @@ -1062,6 +1082,9 @@ func TestAzureKeyVaultSecretManagerGetSecret(t *testing.T) { makeValidSecretManagerTestCaseCustom(badSecretWithProperty), makeValidSecretManagerTestCaseCustom(setPubRSAKey), makeValidSecretManagerTestCaseCustom(setPubECKey), + makeValidSecretManagerTestCaseCustom(secretNotFound), + makeValidSecretManagerTestCaseCustom(certNotFound), + makeValidSecretManagerTestCaseCustom(keyNotFound), makeValidSecretManagerTestCaseCustom(setCertificate), makeValidSecretManagerTestCaseCustom(badSecretType), makeValidSecretManagerTestCaseCustom(setSecretWithTag), diff --git a/pkg/provider/gcp/secretmanager/client.go b/pkg/provider/gcp/secretmanager/client.go index 83f5e2e8d66..73754ea377f 100644 --- a/pkg/provider/gcp/secretmanager/client.go +++ b/pkg/provider/gcp/secretmanager/client.go @@ -114,6 +114,14 @@ func (c *Client) DeleteSecret(ctx context.Context, remoteRef esv1beta1.PushRemot return c.smClient.DeleteSecret(ctx, deleteSecretVersionReq) } +func parseError(err error) error { + var gerr *apierror.APIError + if errors.As(err, &gerr) && gerr.GRPCStatus().Code() == codes.NotFound { + return esv1beta1.NoSecretError{} + } + return err +} + // PushSecret pushes a kubernetes secret key into gcp provider Secret. func (c *Client) PushSecret(ctx context.Context, payload []byte, remoteRef esv1beta1.PushRemoteRef) error { createSecretReq := &secretmanagerpb.CreateSecretRequest{ @@ -325,6 +333,7 @@ func (c *Client) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretData Name: fmt.Sprintf("projects/%s/secrets/%s/versions/%s", c.store.ProjectID, ref.Key, version), } result, err := c.smClient.AccessSecretVersion(ctx, req) + err = parseError(err) if err != nil { return nil, fmt.Errorf(errClientGetSecretAccess, err) } diff --git a/pkg/provider/gcp/secretmanager/client_test.go b/pkg/provider/gcp/secretmanager/client_test.go index 659438e51c0..9c524e74010 100644 --- a/pkg/provider/gcp/secretmanager/client_test.go +++ b/pkg/provider/gcp/secretmanager/client_test.go @@ -113,6 +113,13 @@ func TestSecretManagerGetSecret(t *testing.T) { smtc.apiOutput.Payload.Data = []byte("testtesttest") smtc.expectedSecret = "testtesttest" } + secretNotFound := func(smtc *secretManagerTestCase) { + fErr := status.Error(codes.NotFound, "failed") + notFoundError, _ := apierror.FromError(fErr) + smtc.apiErr = notFoundError + smtc.expectedSecret = "" + smtc.expectError = esv1beta1.NoSecretErr.Error() + } // good case: with a dot in the key name setDotRef := func(smtc *secretManagerTestCase) { smtc.ref = &esv1beta1.ExternalSecretDataRemoteRef{ @@ -164,6 +171,7 @@ func TestSecretManagerGetSecret(t *testing.T) { successCases := []*secretManagerTestCase{ makeValidSecretManagerTestCase(), makeValidSecretManagerTestCaseCustom(setSecretString), + makeValidSecretManagerTestCaseCustom(secretNotFound), makeValidSecretManagerTestCaseCustom(setCustomVersion), makeValidSecretManagerTestCaseCustom(setAPIErr), makeValidSecretManagerTestCaseCustom(setCustomRef), diff --git a/pkg/provider/kubernetes/client.go b/pkg/provider/kubernetes/client.go index 30705b2543a..9ac593fb84b 100644 --- a/pkg/provider/kubernetes/client.go +++ b/pkg/provider/kubernetes/client.go @@ -18,6 +18,7 @@ import ( "encoding/json" "fmt" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" @@ -60,6 +61,9 @@ func (c *Client) PushSecret(ctx context.Context, value []byte, remoteRef esv1bet func (c *Client) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) { secret, err := c.userSecretClient.Get(ctx, ref.Key, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + return nil, esv1beta1.NoSecretError{} + } if err != nil { return nil, err } diff --git a/pkg/provider/kubernetes/client_test.go b/pkg/provider/kubernetes/client_test.go index 856e20e3dc0..0e200957fed 100644 --- a/pkg/provider/kubernetes/client_test.go +++ b/pkg/provider/kubernetes/client_test.go @@ -21,7 +21,9 @@ import ( "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" ) @@ -34,6 +36,7 @@ type fakeClient struct { t *testing.T secretMap map[string]corev1.Secret expectedListOptions metav1.ListOptions + err error } func (fk fakeClient) Get(ctx context.Context, name string, opts metav1.GetOptions) (*corev1.Secret, error) { @@ -42,7 +45,7 @@ func (fk fakeClient) Get(ctx context.Context, name string, opts metav1.GetOption if !ok { return nil, errors.New(errSomethingWentWrong) } - return &secret, nil + return &secret, fk.err } func (fk fakeClient) List(ctx context.Context, opts metav1.ListOptions) (*corev1.SecretList, error) { @@ -68,6 +71,28 @@ func TestGetSecret(t *testing.T) { want []byte wantErr bool }{ + { + name: "secretNotFound", + fields: fields{ + Client: fakeClient{ + t: t, + secretMap: map[string]corev1.Secret{ + "mysec": { + Data: map[string][]byte{ + "token": []byte(`foobar`), + }, + }, + }, + err: apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: "Secret"}, "secret"), + }, + Namespace: "default", + }, + ref: esv1beta1.ExternalSecretDataRemoteRef{ + Key: "mysec", + Property: "token", + }, + wantErr: true, + }, { name: "err GetSecretMap", fields: fields{ From 5ef3b23a681de54cc6613a390bb90391c110ed5a Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Thu, 19 Jan 2023 17:25:47 +0100 Subject: [PATCH 03/62] feat: make cache generic, refactor feature flags (#1640) Signed-off-by: Moritz Johner Signed-off-by: Moritz Johner --- cmd/root.go | 27 ++++----- e2e/framework/addon/eso.go | 16 +++++ e2e/framework/eso.go | 55 ++++++++++++++++++ e2e/framework/log/log.go | 4 +- e2e/framework/testcase.go | 1 + go.mod | 2 +- pkg/cache/cache.go | 99 +++++++++++++++++++++++++++++++ pkg/cache/cache_test.go | 99 +++++++++++++++++++++++++++++++ pkg/feature/feature.go | 38 ++++++++++++ pkg/provider/aws/auth/auth.go | 42 ++++++++------ pkg/provider/vault/cache.go | 106 ---------------------------------- pkg/provider/vault/vault.go | 80 +++++++++++++------------ 12 files changed, 389 insertions(+), 180 deletions(-) create mode 100644 pkg/cache/cache.go create mode 100644 pkg/cache/cache_test.go create mode 100644 pkg/feature/feature.go delete mode 100644 pkg/provider/vault/cache.go diff --git a/cmd/root.go b/cmd/root.go index 3537099442b..d1e3ff6ccdb 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -39,8 +39,7 @@ import ( "github.com/external-secrets/external-secrets/pkg/controllers/externalsecret" "github.com/external-secrets/external-secrets/pkg/controllers/pushsecret" "github.com/external-secrets/external-secrets/pkg/controllers/secretstore" - awsauth "github.com/external-secrets/external-secrets/pkg/provider/aws/auth" - "github.com/external-secrets/external-secrets/pkg/provider/vault" + "github.com/external-secrets/external-secrets/pkg/feature" ) var ( @@ -72,9 +71,6 @@ var ( crdRequeueInterval time.Duration certCheckInterval time.Duration certLookaheadInterval time.Duration - enableAWSSession bool - enableVaultTokenCache bool - vaultTokenCacheSize int tlsCiphers string tlsMinVersion string ) @@ -205,19 +201,19 @@ var rootCmd = &cobra.Command{ os.Exit(1) } } - if enableAWSSession { - awsauth.EnableCache = true - } - if enableVaultTokenCache { - vault.EnableCache = true - vault.VaultClientCache.Size = vaultTokenCacheSize + + fs := feature.Features() + for _, f := range fs { + if f.Initialize == nil { + continue + } + f.Initialize() } setupLog.Info("starting manager") if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { setupLog.Error(err, "problem running manager") os.Exit(1) } - }, } @@ -244,7 +240,8 @@ func init() { rootCmd.Flags().BoolVar(&enableConfigMapsCache, "enable-configmaps-caching", false, "Enable secrets caching for external-secrets pod.") rootCmd.Flags().DurationVar(&storeRequeueInterval, "store-requeue-interval", time.Minute*5, "Default Time duration between reconciling (Cluster)SecretStores") rootCmd.Flags().BoolVar(&enableFloodGate, "enable-flood-gate", true, "Enable flood gate. External secret will be reconciled only if the ClusterStore or Store have an healthy or unknown state.") - rootCmd.Flags().BoolVar(&enableAWSSession, "experimental-enable-aws-session-cache", false, "Enable experimental AWS session cache. External secret will reuse the AWS session without creating a new one on each request.") - rootCmd.Flags().BoolVar(&enableVaultTokenCache, "experimental-enable-vault-token-cache", false, "Enable experimental Vault token cache. External secrets will reuse the Vault token without creating a new one on each request.") - rootCmd.Flags().IntVar(&vaultTokenCacheSize, "experimental-vault-token-cache-size", 100, "Maximum size of Vault token cache. Only used if --experimental-enable-vault-token-cache is set.") + fs := feature.Features() + for _, f := range fs { + rootCmd.Flags().AddFlagSet(f.Flags) + } } diff --git a/e2e/framework/addon/eso.go b/e2e/framework/addon/eso.go index e72ecd5c7d9..1db2ee45503 100644 --- a/e2e/framework/addon/eso.go +++ b/e2e/framework/addon/eso.go @@ -57,6 +57,22 @@ func NewESO(mutators ...MutationFunc) *ESO { Key: installCRDsVar, Value: "false", }, + { + Key: "concurrent", + Value: "100", + }, + { + Key: "extraArgs.experimental-enable-vault-token-cache", + Value: "true", + }, + { + Key: "extraArgs.experimental-enable-aws-session-cache", + Value: "true", + }, + { + Key: "extraArgs.experimental-vault-token-cache-size", + Value: "10", + }, }, }, } diff --git a/e2e/framework/eso.go b/e2e/framework/eso.go index 1900d377fea..6ee448ca6d9 100644 --- a/e2e/framework/eso.go +++ b/e2e/framework/eso.go @@ -20,11 +20,16 @@ import ( "encoding/json" "time" + //nolint + . "github.com/onsi/gomega" + v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" + "github.com/external-secrets/external-secrets-e2e/framework/log" esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" ) @@ -45,6 +50,56 @@ func (f *Framework) WaitForSecretValue(namespace, name string, expected *v1.Secr return secret, err } +func (f *Framework) printESDebugLogs(esName, esNamespace string) { + // fetch es and print status condition + var es esv1beta1.ExternalSecret + err := f.CRClient.Get(context.Background(), types.NamespacedName{ + Name: esName, + Namespace: esNamespace, + }, &es) + Expect(err).ToNot(HaveOccurred()) + log.Logf("resourceVersion=%s", es.Status.SyncedResourceVersion) + for _, cond := range es.Status.Conditions { + log.Logf("condition: status=%s type=%s reason=%s message=%s", cond.Status, cond.Type, cond.Reason, cond.Message) + } + // list events for given + evs, err := f.KubeClientSet.CoreV1().Events(esNamespace).List(context.Background(), metav1.ListOptions{ + FieldSelector: "involvedObject.name=" + esName + ",involvedObject.kind=ExternalSecret", + }) + Expect(err).ToNot(HaveOccurred()) + for _, ev := range evs.Items { + log.Logf("ev reason=%s message=%s", ev.Reason, ev.Message) + } + + // print most recent logs of default eso installation + podList, err := f.KubeClientSet.CoreV1().Pods("default").List( + context.Background(), + metav1.ListOptions{LabelSelector: "app.kubernetes.io/instance=eso,app.kubernetes.io/name=external-secrets"}) + Expect(err).ToNot(HaveOccurred()) + numLines := int64(60) + for i := range podList.Items { + pod := podList.Items[i] + for _, con := range pod.Spec.Containers { + for _, b := range []bool{true, false} { + resp := f.KubeClientSet.CoreV1().Pods(pod.Namespace).GetLogs(pod.Name, &v1.PodLogOptions{ + Container: con.Name, + Previous: b, + TailLines: &numLines, + }).Do(context.TODO()) + err := resp.Error() + if err != nil { + continue + } + logs, err := resp.Raw() + if err != nil { + continue + } + log.Logf("[%s]: %s", "eso", string(logs)) + } + } + } +} + func equalSecrets(exp, ts *v1.Secret) bool { if exp.Type != ts.Type { return false diff --git a/e2e/framework/log/log.go b/e2e/framework/log/log.go index 109370ae7d5..61c9f97127a 100644 --- a/e2e/framework/log/log.go +++ b/e2e/framework/log/log.go @@ -3,7 +3,7 @@ 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 + 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, @@ -19,5 +19,5 @@ import ( // Logf logs the format string to ginkgo stdout. func Logf(format string, args ...interface{}) { - ginkgo.GinkgoWriter.Printf(format, args...) + ginkgo.GinkgoWriter.Printf(format+"\n", args...) } diff --git a/e2e/framework/testcase.go b/e2e/framework/testcase.go index d5e28b8218c..f05bb4624fb 100644 --- a/e2e/framework/testcase.go +++ b/e2e/framework/testcase.go @@ -96,6 +96,7 @@ func TableFunc(f *Framework, prov SecretStoreProvider) func(...func(*TestCase)) // wait for Kind=Secret to have the expected data secret, err := tc.Framework.WaitForSecretValue(tc.Framework.Namespace.Name, TargetSecretName, tc.ExpectedSecret) if err != nil { + f.printESDebugLogs(tc.ExternalSecret.Name, tc.ExternalSecret.Namespace) log.Logf("Did not match. Expected: %+v, Got: %+v", tc.ExpectedSecret, secret) } diff --git a/go.mod b/go.mod index b0d2d94b3b2..9382b7b5e86 100644 --- a/go.mod +++ b/go.mod @@ -98,6 +98,7 @@ require ( github.com/hashicorp/golang-lru v0.5.4 github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0 github.com/sethvargo/go-password v0.2.0 + github.com/spf13/pflag v1.0.5 sigs.k8s.io/yaml v1.3.0 ) @@ -206,7 +207,6 @@ require ( github.com/shopspring/decimal v1.3.1 // indirect github.com/sony/gobreaker v0.5.0 // indirect github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go new file mode 100644 index 00000000000..cd78f7615d6 --- /dev/null +++ b/pkg/cache/cache.go @@ -0,0 +1,99 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cache + +import ( + "fmt" + + lru "github.com/hashicorp/golang-lru" +) + +// Cache is a generic lru cache that allows you to +// lookup values using a key and a version. +// By design, this cache allows access to only a single version of a given key. +// A version mismatch is considered a cache miss and the key gets evicted if it exists. +// When a key is evicted a optional cleanup function is called. +type Cache[T any] struct { + lru *lru.Cache + size int + cleanupFunc cleanupFunc[T] +} + +// Key is the cache lookup key. +type Key struct { + Name string + Namespace string + Kind string +} + +type value[T any] struct { + Version string + Client T +} + +type cleanupFunc[T any] func(client T) + +// New constructs a new lru cache with the desired size and cleanup func. +func New[T any](size int, cleanup cleanupFunc[T]) (*Cache[T], error) { + lruCache, err := lru.NewWithEvict(size, func(_, val any) { + if cleanup == nil { + return + } + cleanup(val.(value[T]).Client) + }) + if err != nil { + return nil, fmt.Errorf("unable to create lru: %w", err) + } + return &Cache[T]{ + lru: lruCache, + size: size, + cleanupFunc: cleanup, + }, nil +} + +// Must creates a new lru cache with the desired size and cleanup func +// This function panics if a error occurrs. +func Must[T any](size int, cleanup cleanupFunc[T]) *Cache[T] { + c, err := New(size, cleanup) + if err != nil { + panic(err) + } + return c +} + +// Get retrieves the desired value using the key and +// compares the version. If there is a mismatch +// it is considered a cache miss and the existing key is purged. +func (c *Cache[T]) Get(version string, key Key) (T, bool) { + val, ok := c.lru.Get(key) + if ok { + cachedClient := val.(value[T]) + if cachedClient.Version == version { + return cachedClient.Client, true + } + c.lru.Remove(key) + } + return value[T]{}.Client, false +} + +// Add adds a new value for the given key/version. +func (c *Cache[T]) Add(version string, key Key, client T) { + c.lru.Add(key, value[T]{Version: version, Client: client}) +} + +// Contains returns true if a value with the given key exists. +func (c *Cache[T]) Contains(key Key) bool { + return c.lru.Contains(key) +} diff --git a/pkg/cache/cache_test.go b/pkg/cache/cache_test.go new file mode 100644 index 00000000000..7215020e82f --- /dev/null +++ b/pkg/cache/cache_test.go @@ -0,0 +1,99 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package cache + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +type client struct{} + +var cacheKey = Key{Name: "foo"} + +func TestCacheAdd(t *testing.T) { + c, err := New[client](1, nil) + if err != nil { + t.Fail() + } + + cl := client{} + c.Add("", cacheKey, cl) + cachedVal, _ := c.Get("", cacheKey) + + assert.EqualValues(t, cl, cachedVal) +} + +func TestCacheContains(t *testing.T) { + c, err := New[client](1, nil) + if err != nil { + t.Fail() + } + + cl := client{} + c.Add("", cacheKey, cl) + exists := c.Contains(cacheKey) + notExists := c.Contains(Key{Name: "does not exist"}) + + assert.True(t, exists) + assert.False(t, notExists) + assert.Nil(t, err) +} + +func TestCacheGet(t *testing.T) { + c, err := New[*client](1, nil) + if err != nil { + t.Fail() + } + cachedVal, ok := c.Get("", cacheKey) + + assert.Nil(t, cachedVal) + assert.False(t, ok) +} + +func TestCacheGetInvalidVersion(t *testing.T) { + var cleanupCalled bool + c, err := New(1, func(client *client) { + cleanupCalled = true + }) + if err != nil { + t.Fail() + } + cl := &client{} + c.Add("", cacheKey, cl) + cachedVal, ok := c.Get("invalid", cacheKey) + + assert.Nil(t, cachedVal) + assert.False(t, ok) + assert.True(t, cleanupCalled) +} + +func TestCacheEvict(t *testing.T) { + var cleanupCalled bool + c, err := New(1, func(client client) { + cleanupCalled = true + }) + if err != nil { + t.Fail() + } + + // add first version + c.Add("", Key{Name: "foo"}, client{}) + assert.False(t, cleanupCalled) + + // adding a second version should evict old one + c.Add("", Key{Name: "bar"}, client{}) + assert.True(t, cleanupCalled) +} diff --git a/pkg/feature/feature.go b/pkg/feature/feature.go new file mode 100644 index 00000000000..f3938cd3a7d --- /dev/null +++ b/pkg/feature/feature.go @@ -0,0 +1,38 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package feature + +import ( + "github.com/spf13/pflag" +) + +// Feature contains the CLI flags that a provider exposes to a user. +// A optional Initialize func is called once the flags have been parsed. +// A provider can use this to do late-initialization using the defined cli args. +type Feature struct { + Flags *pflag.FlagSet + Initialize func() +} + +var features = make([]Feature, 0) + +// Features returns all registered features. +func Features() []Feature { + return features +} + +// Register registers a new feature. +func Register(f Feature) { + features = append(features, f) +} diff --git a/pkg/provider/aws/auth/auth.go b/pkg/provider/aws/auth/auth.go index 773528f0c56..8b482a2bc99 100644 --- a/pkg/provider/aws/auth/auth.go +++ b/pkg/provider/aws/auth/auth.go @@ -26,6 +26,7 @@ import ( "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/sts" "github.com/aws/aws-sdk-go/service/sts/stsiface" + "github.com/spf13/pflag" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes" @@ -34,6 +35,8 @@ import ( ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config" esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" + "github.com/external-secrets/external-secrets/pkg/cache" + "github.com/external-secrets/external-secrets/pkg/feature" "github.com/external-secrets/external-secrets/pkg/provider/aws/util" ) @@ -44,17 +47,10 @@ type Config struct { APIRetries int } -type SessionCache struct { - Name string - Namespace string - Kind string - ResourceVersion string -} - var ( - log = ctrl.Log.WithName("provider").WithName("aws") - sessions = make(map[SessionCache]*session.Session) - EnableCache bool + log = ctrl.Log.WithName("provider").WithName("aws") + enableSessionCache bool + sessionCache *cache.Cache[*session.Session] ) const ( @@ -71,6 +67,15 @@ const ( errMissingAKID = "missing AccessKeyID" ) +func init() { + fs := pflag.NewFlagSet("aws-auth", pflag.ExitOnError) + fs.BoolVar(&enableSessionCache, "experimental-enable-aws-session-cache", false, "Enable experimental AWS session cache. External secret will reuse the AWS session without creating a new one on each request.") + feature.Register(feature.Feature{ + Flags: fs, + }) + sessionCache = cache.Must[*session.Session](1024, nil) +} + // New creates a new aws session based on the provided store // it uses the following authentication mechanisms in order: // * service-account token authentication via AssumeRoleWithWebIdentity @@ -111,7 +116,7 @@ func New(ctx context.Context, store esv1beta1.GenericStore, kube client.Client, config.WithRegion(prov.Region) } - sess, err := getAWSSession(config, EnableCache, store.GetName(), store.GetTypeMeta().Kind, namespace, store.GetObjectMeta().ResourceVersion) + sess, err := getAWSSession(config, enableSessionCache, store.GetName(), store.GetTypeMeta().Kind, namespace, store.GetObjectMeta().ResourceVersion) if err != nil { return nil, err } @@ -327,17 +332,16 @@ func DefaultSTSProvider(sess *session.Session) stsiface.STSAPI { // getAWSSession checks if an AWS session should be reused // it returns the aws session or an error. func getAWSSession(config *aws.Config, enableCache bool, name, kind, namespace, resourceVersion string) (*session.Session, error) { - tmpSession := SessionCache{ - Name: name, - Namespace: namespace, - Kind: kind, - ResourceVersion: resourceVersion, + key := cache.Key{ + Name: name, + Namespace: namespace, + Kind: kind, } if enableCache { - sess, ok := sessions[tmpSession] + sess, ok := sessionCache.Get(resourceVersion, key) if ok { - log.Info("reusing aws session", "SecretStore", tmpSession.Name, "namespace", tmpSession.Namespace, "kind", tmpSession.Kind, "resourceversion", tmpSession.ResourceVersion) + log.Info("reusing aws session", "SecretStore", key.Name, "namespace", key.Namespace, "kind", key.Kind, "resourceversion", resourceVersion) return sess, nil } } @@ -354,7 +358,7 @@ func getAWSSession(config *aws.Config, enableCache bool, name, kind, namespace, } if enableCache { - sessions[tmpSession] = sess + sessionCache.Add(resourceVersion, key, sess) } return sess, nil } diff --git a/pkg/provider/vault/cache.go b/pkg/provider/vault/cache.go deleted file mode 100644 index 263b10e36e0..00000000000 --- a/pkg/provider/vault/cache.go +++ /dev/null @@ -1,106 +0,0 @@ -/* -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 implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package vault - -import ( - "context" - "errors" - "fmt" - "sync" - - lru "github.com/hashicorp/golang-lru" - - esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" -) - -type clientCache struct { - cache *lru.Cache - Size int - initialized bool - mu sync.Mutex -} - -type clientCacheKey struct { - Name string - Namespace string - Kind string -} - -type clientCacheValue struct { - ResourceVersion string - Client Client -} - -func (c *clientCache) initialize() error { - if !c.initialized { - var err error - c.cache, err = lru.New(c.Size) - if err != nil { - return fmt.Errorf(errVaultCacheCreate, err) - } - c.initialized = true - } - return nil -} - -func (c *clientCache) get(ctx context.Context, store esv1beta1.GenericStore, key clientCacheKey) (Client, bool, error) { - value, ok := c.cache.Get(key) - if ok { - cachedClient := value.(clientCacheValue) - if cachedClient.ResourceVersion == store.GetObjectMeta().ResourceVersion { - return cachedClient.Client, true, nil - } - // revoke token and clear old item from cache if resource has been updated - err := revokeTokenIfValid(ctx, cachedClient.Client) - if err != nil { - return nil, false, err - } - c.cache.Remove(key) - } - return nil, false, nil -} - -func (c *clientCache) add(ctx context.Context, store esv1beta1.GenericStore, key clientCacheKey, client Client) error { - // don't let the LRU cache evict items - // remove the oldest item manually when needed so we can do some cleanup - for c.cache.Len() >= c.Size { - _, value, ok := c.cache.RemoveOldest() - if !ok { - return errors.New(errVaultCacheRemove) - } - cachedClient := value.(clientCacheValue) - err := revokeTokenIfValid(ctx, cachedClient.Client) - if err != nil { - return fmt.Errorf(errVaultRevokeToken, err) - } - } - evicted := c.cache.Add(key, clientCacheValue{ResourceVersion: store.GetObjectMeta().ResourceVersion, Client: client}) - if evicted { - return errors.New(errVaultCacheEviction) - } - return nil -} - -func (c *clientCache) contains(key clientCacheKey) bool { - return c.cache.Contains(key) -} - -func (c *clientCache) lock() { - c.mu.Lock() -} - -func (c *clientCache) unlock() { - c.mu.Unlock() -} diff --git a/pkg/provider/vault/vault.go b/pkg/provider/vault/vault.go index f4a214190a6..b0579a49f7b 100644 --- a/pkg/provider/vault/vault.go +++ b/pkg/provider/vault/vault.go @@ -32,6 +32,7 @@ import ( approle "github.com/hashicorp/vault/api/auth/approle" authkubernetes "github.com/hashicorp/vault/api/auth/kubernetes" authldap "github.com/hashicorp/vault/api/auth/ldap" + "github.com/spf13/pflag" "github.com/tidwall/gjson" authenticationv1 "k8s.io/api/authentication/v1" corev1 "k8s.io/api/core/v1" @@ -45,15 +46,18 @@ import ( esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" + "github.com/external-secrets/external-secrets/pkg/cache" + "github.com/external-secrets/external-secrets/pkg/feature" "github.com/external-secrets/external-secrets/pkg/find" "github.com/external-secrets/external-secrets/pkg/utils" ) var ( - _ esv1beta1.Provider = &connector{} - _ esv1beta1.SecretsClient = &client{} - EnableCache bool - VaultClientCache clientCache + _ esv1beta1.Provider = &connector{} + _ esv1beta1.SecretsClient = &client{} + enableCache bool + logger = ctrl.Log.WithName("provider").WithName("vault") + clientCache *cache.Cache[Client] ) const ( @@ -198,14 +202,6 @@ type client struct { storeKind string } -func init() { - esv1beta1.Register(&connector{ - newVaultClient: newVaultClient, - }, &esv1beta1.SecretStoreProvider{ - Vault: &esv1beta1.VaultProvider{}, - }) -} - func newVaultClient(c *vault.Config) (Client, error) { cl, err := vault.NewClient(c) if err != nil { @@ -227,30 +223,17 @@ func newVaultClient(c *vault.Config) (Client, error) { return out, nil } -func getVaultClient(ctx context.Context, c *connector, store esv1beta1.GenericStore, cfg *vault.Config) (Client, error) { +func getVaultClient(c *connector, store esv1beta1.GenericStore, cfg *vault.Config) (Client, error) { isStaticToken := store.GetSpec().Provider.Vault.Auth.TokenSecretRef != nil - useCache := EnableCache && !isStaticToken - - if useCache { - VaultClientCache.lock() - defer VaultClientCache.unlock() + useCache := enableCache && !isStaticToken - err := VaultClientCache.initialize() - if err != nil { - return nil, err - } - } - - key := clientCacheKey{ + key := cache.Key{ Name: store.GetObjectMeta().Name, Namespace: store.GetObjectMeta().Namespace, Kind: store.GetTypeMeta().Kind, } if useCache { - client, ok, err := VaultClientCache.get(ctx, store, key) - if err != nil { - return nil, err - } + client, ok := clientCache.Get(store.GetObjectMeta().ResourceVersion, key) if ok { return client, nil } @@ -261,11 +244,8 @@ func getVaultClient(ctx context.Context, c *connector, store esv1beta1.GenericSt return nil, fmt.Errorf(errVaultClient, err) } - if useCache && !VaultClientCache.contains(key) { - err = VaultClientCache.add(ctx, store, key, client) - if err != nil { - return nil, err - } + if useCache && !clientCache.Contains(key) { + clientCache.Add(store.GetObjectMeta().ResourceVersion, key, client) } return client, nil } @@ -306,7 +286,7 @@ func (c *connector) newClient(ctx context.Context, store esv1beta1.GenericStore, kube: kube, corev1: corev1, store: vaultSpec, - log: ctrl.Log.WithName("provider").WithName("vault"), + log: logger, namespace: namespace, storeKind: store.GetObjectKind().GroupVersionKind().Kind, } @@ -316,7 +296,7 @@ func (c *connector) newClient(ctx context.Context, store esv1beta1.GenericStore, return nil, err } - client, err := getVaultClient(ctx, c, store, cfg) + client, err := getVaultClient(c, store, cfg) if err != nil { return nil, fmt.Errorf(errVaultClient, err) } @@ -723,7 +703,7 @@ func getTypedKey(data map[string]interface{}, key string) ([]byte, error) { func (v *client) Close(ctx context.Context) error { // Revoke the token if we have one set, it wasn't sourced from a TokenSecretRef, // and token caching isn't enabled - if !EnableCache && v.client.Token() != "" && v.store.Auth.TokenSecretRef == nil { + if !enableCache && v.client.Token() != "" && v.store.Auth.TokenSecretRef == nil { err := revokeTokenIfValid(ctx, v.client) if err != nil { return err @@ -1415,3 +1395,29 @@ func (v *client) requestTokenWithCertAuth(ctx context.Context, certAuth *esv1bet v.client.SetToken(token) return nil } + +func init() { + var vaultTokenCacheSize int + fs := pflag.NewFlagSet("vault", pflag.ExitOnError) + fs.BoolVar(&enableCache, "experimental-enable-vault-token-cache", false, "Enable experimental Vault token cache. External secrets will reuse the Vault token without creating a new one on each request.") + fs.IntVar(&vaultTokenCacheSize, "experimental-vault-token-cache-size", 100, "Maximum size of Vault token cache. Only used if --experimental-enable-vault-token-cache is set.") + lateInit := func() { + logger.Info("initializing vault cache with size=%d", vaultTokenCacheSize) + clientCache = cache.Must(vaultTokenCacheSize, func(client Client) { + err := revokeTokenIfValid(context.Background(), client) + if err != nil { + logger.Error(err, "unable to revoke cached token on eviction") + } + }) + } + feature.Register(feature.Feature{ + Flags: fs, + Initialize: lateInit, + }) + + esv1beta1.Register(&connector{ + newVaultClient: newVaultClient, + }, &esv1beta1.SecretStoreProvider{ + Vault: &esv1beta1.VaultProvider{}, + }) +} From ac9993f151898ba47bbaa3abdcfb4564f1d59bf3 Mon Sep 17 00:00:00 2001 From: Gareth Evans Date: Thu, 19 Jan 2023 16:31:51 +0000 Subject: [PATCH 04/62] :books: use more inclusive language (#1927) Signed-off-by: Gareth Evans --- pkg/provider/azure/keyvault/keyvault_test.go | 4 ++-- pkg/provider/gcp/secretmanager/provider.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/provider/azure/keyvault/keyvault_test.go b/pkg/provider/azure/keyvault/keyvault_test.go index 53452c50110..f4123270765 100644 --- a/pkg/provider/azure/keyvault/keyvault_test.go +++ b/pkg/provider/azure/keyvault/keyvault_test.go @@ -848,7 +848,7 @@ func TestAzureKeyVaultSecretManagerGetSecret(t *testing.T) { smtc.secretName = "name" smtc.expectedSecret = "" smtc.expectError = fmt.Sprintf("unknown Azure Keyvault object Type for %s", smtc.secretName) - smtc.ref.Key = fmt.Sprintf("dummy/%s", smtc.secretName) + smtc.ref.Key = fmt.Sprintf("example/%s", smtc.secretName) } setSecretWithTag := func(smtc *secretManagerTestCase) { @@ -1193,7 +1193,7 @@ func TestAzureKeyVaultSecretManagerGetSecretMap(t *testing.T) { smtc.secretName = "name" smtc.expectedSecret = "" smtc.expectError = fmt.Sprintf("unknown Azure Keyvault object Type for %s", smtc.secretName) - smtc.ref.Key = fmt.Sprintf("dummy/%s", smtc.secretName) + smtc.ref.Key = fmt.Sprintf("example/%s", smtc.secretName) } setSecretTags := func(smtc *secretManagerTestCase) { diff --git a/pkg/provider/gcp/secretmanager/provider.go b/pkg/provider/gcp/secretmanager/provider.go index 40447a574de..fd346a1b009 100644 --- a/pkg/provider/gcp/secretmanager/provider.go +++ b/pkg/provider/gcp/secretmanager/provider.go @@ -85,7 +85,7 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore, // allow SecretStore controller validation to pass // when using referent namespace. if namespace == "" && isClusterKind && isReferentSpec(gcpStore) { - // dummy smClient to prevent closing the client twice + // placeholder smClient to prevent closing the client twice client.smClient, _ = secretmanager.NewClient(ctx, option.WithTokenSource(oauth2.StaticTokenSource(&oauth2.Token{}))) return client, nil } From 6862c9c637120456a61128d2e353f813e24e5d57 Mon Sep 17 00:00:00 2001 From: Thibault Cohen <47721+titilambert@users.noreply.github.com> Date: Mon, 23 Jan 2023 13:43:50 -0500 Subject: [PATCH 05/62] :sparkles: Support template for webhook jsonpath (#1939) * Support template for webhook jsonpath Signed-off-by: Thibault Cohen <47721+titilambert@users.noreply.github.com> --- pkg/provider/webhook/webhook.go | 14 ++++++++--- pkg/provider/webhook/webhook_test.go | 35 ++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/pkg/provider/webhook/webhook.go b/pkg/provider/webhook/webhook.go index 5aec7e12a0d..595f0dd764e 100644 --- a/pkg/provider/webhook/webhook.go +++ b/pkg/provider/webhook/webhook.go @@ -141,14 +141,22 @@ func (w *WebHook) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDat return nil, err } // Only parse as json if we have a jsonpath set - if provider.Result.JSONPath != "" { + data, err := w.getTemplateData(ctx, ref, provider.Secrets) + if err != nil { + return nil, err + } + resultJSONPath, err := executeTemplateString(provider.Result.JSONPath, data) + if err != nil { + return nil, err + } + if resultJSONPath != "" { jsondata := interface{}(nil) if err := yaml.Unmarshal(result, &jsondata); err != nil { return nil, fmt.Errorf("failed to parse response json: %w", err) } - jsondata, err = jsonpath.Get(provider.Result.JSONPath, jsondata) + jsondata, err = jsonpath.Get(resultJSONPath, jsondata) if err != nil { - return nil, fmt.Errorf("failed to get response path %s: %w", provider.Result.JSONPath, err) + return nil, fmt.Errorf("failed to get response path %s: %w", resultJSONPath, err) } jsonvalue, ok := jsondata.(string) if !ok { diff --git a/pkg/provider/webhook/webhook_test.go b/pkg/provider/webhook/webhook_test.go index fd2156f8989..90f169504b3 100644 --- a/pkg/provider/webhook/webhook_test.go +++ b/pkg/provider/webhook/webhook_test.go @@ -41,6 +41,7 @@ type args struct { Body string `json:"body,omitempty"` Timeout string `json:"timeout,omitempty"` Key string `json:"key,omitempty"` + Property string `json:"property,omitempty"` Version string `json:"version,omitempty"` JSONPath string `json:"jsonpath,omitempty"` Response string `json:"response,omitempty"` @@ -137,6 +138,7 @@ args: response: secret-value want: path: /api/getsecret?id=testkey&version=1 + err: '' result: secret-value --- case: good json @@ -148,6 +150,7 @@ args: response: '{"result":{"thesecret":"secret-value"}}' want: path: /api/getsecret?id=testkey&version=1 + err: '' result: secret-value --- case: good json map @@ -159,6 +162,7 @@ args: response: '{"result":{"thesecret":"secret-value","alsosecret":"another-value"}}' want: path: /api/getsecret?id=testkey&version=1 + err: '' resultmap: thesecret: secret-value alsosecret: another-value @@ -171,6 +175,7 @@ args: response: '{"thesecret":"secret-value","alsosecret":"another-value"}' want: path: /api/getsecret?id=testkey&version=1 + err: '' resultmap: thesecret: secret-value alsosecret: another-value @@ -201,6 +206,31 @@ want: resultmap: thesecret: secret-value alsosecret: another-value +--- +case: good json with good templated jsonpath +args: + url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }} + key: testkey + property: thesecret + version: 1 + jsonpath: $.result.{{ .remoteRef.property }} + response: '{"result":{"thesecret":"secret-value"}}' +want: + path: /api/getsecret?id=testkey&version=1 + err: '' + result: secret-value +--- +case: good json with bad temlated jsonpath +args: + url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }} + key: testkey + property: thesecret + version: 1 + jsonpath: $.result.{{ .remoteRef.property } + response: '{"result":{"thesecret":"secret-value"}}' +want: + path: /api/getsecret?id=testkey&version=1 + err: 'template: webhooktemplate:1: unexpected "}" in operand' ` func TestWebhookGetSecret(t *testing.T) { @@ -294,8 +324,9 @@ func testGetSecretMap(tc testCase, t *testing.T, client esv1beta1.SecretsClient) func testGetSecret(tc testCase, t *testing.T, client esv1beta1.SecretsClient) { testRef := esv1beta1.ExternalSecretDataRemoteRef{ - Key: tc.Args.Key, - Version: tc.Args.Version, + Key: tc.Args.Key, + Property: tc.Args.Property, + Version: tc.Args.Version, } ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() From ff88395c099caae3ea48f9ab6fda6a83c58b0c95 Mon Sep 17 00:00:00 2001 From: Thibault Cohen <47721+titilambert@users.noreply.github.com> Date: Tue, 24 Jan 2023 09:30:20 -0500 Subject: [PATCH 06/62] Add jsonpath filter support to webhook (#1940) * Add jsonpath filter support to webhook Signed-off-by: Thibault Cohen <47721+titilambert@users.noreply.github.com> * Fix tests Signed-off-by: Thibault Cohen <47721+titilambert@users.noreply.github.com> Signed-off-by: Thibault Cohen <47721+titilambert@users.noreply.github.com> --- pkg/provider/webhook/webhook.go | 9 ++++++++- pkg/provider/webhook/webhook_test.go | 25 ++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/pkg/provider/webhook/webhook.go b/pkg/provider/webhook/webhook.go index 595f0dd764e..57bbeb50834 100644 --- a/pkg/provider/webhook/webhook.go +++ b/pkg/provider/webhook/webhook.go @@ -160,7 +160,14 @@ func (w *WebHook) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDat } jsonvalue, ok := jsondata.(string) if !ok { - return nil, fmt.Errorf("failed to get response (wrong type: %T)", jsondata) + jsonvalues, ok := jsondata.([]interface{}) + if !ok { + return nil, fmt.Errorf("failed to get response (wrong type: %T)", jsondata) + } + if len(jsonvalues) == 0 { + return nil, fmt.Errorf("filter worked but didn't get any result") + } + jsonvalue = jsonvalues[0].(string) } return []byte(jsonvalue), nil } diff --git a/pkg/provider/webhook/webhook_test.go b/pkg/provider/webhook/webhook_test.go index 90f169504b3..e7739101af9 100644 --- a/pkg/provider/webhook/webhook_test.go +++ b/pkg/provider/webhook/webhook_test.go @@ -220,7 +220,19 @@ want: err: '' result: secret-value --- -case: good json with bad temlated jsonpath +case: good json with jsonpath filter +args: + url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }} + key: testkey + version: 1 + jsonpath: $.secrets[?@.name=="thesecret"].value + response: '{"secrets": [{"name": "thesecret", "value": "secret-value"}, {"name": "alsosecret", "value": "another-value"}]}' +want: + path: /api/getsecret?id=testkey&version=1 + err: '' + result: secret-value +--- +case: good json with bad templated jsonpath args: url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }} key: testkey @@ -231,6 +243,17 @@ args: want: path: /api/getsecret?id=testkey&version=1 err: 'template: webhooktemplate:1: unexpected "}" in operand' +--- +case: error with jsonpath filter empty results +args: + url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }} + key: testkey + version: 1 + jsonpath: $.secrets[?@.name=="thebadsecret"].value + response: '{"secrets": [{"name": "thesecret", "value": "secret-value"}, {"name": "alsosecret", "value": "another-value"}]}' +want: + path: /api/getsecret?id=testkey&version=1 + err: "filter worked but didn't get any result" ` func TestWebhookGetSecret(t *testing.T) { From bde9f94be300f047c7f5d5b2483b80ee8c26c439 Mon Sep 17 00:00:00 2001 From: Tobias Germer Date: Tue, 24 Jan 2023 15:40:10 +0100 Subject: [PATCH 07/62] Fix wrong IAM permissions in docs for the AWS Parameter Store (#1949) Signed-off-by: Tobias Germer --- docs/provider/aws-parameter-store.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/provider/aws-parameter-store.md b/docs/provider/aws-parameter-store.md index 988aa78f99b..3cc3cbc8c34 100644 --- a/docs/provider/aws-parameter-store.md +++ b/docs/provider/aws-parameter-store.md @@ -31,9 +31,8 @@ Create a IAM Policy to pin down access to secrets matching `dev-*`, for further "Effect": "Allow", "Action": [ "ssm:GetParameter", - "ssm:GetParameterWithContext", - "ssm:ListTagsForResourceWithContext", - "ssm:DescribeParametersWithContext", + "ssm:ListTagsForResource", + "ssm:DescribeParameters" ], "Resource": "arn:aws:ssm:us-east-2:1234567889911:parameter/dev-*" } From 322f61dbaadc7d3c4991f186de1243bac8f553d1 Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Tue, 24 Jan 2023 18:00:17 +0100 Subject: [PATCH 08/62] :bug: no need to use cgo (#1935) Signed-off-by: Moritz Johner Signed-off-by: Moritz Johner --- .github/workflows/ci.yml | 2 +- .github/workflows/rebuild-image.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08003585e1c..617c8ca5700 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -185,7 +185,7 @@ jobs: build-platform: "linux/amd64,linux/arm64" tag-suffix: "-ubi" - dockerfile: "Dockerfile.ubi" - build-args: "CGO_ENABLED=1 GOEXPERIMENT=boringcrypto" + build-args: "CGO_ENABLED=0 GOEXPERIMENT=boringcrypto" build-arch: "amd64" build-platform: "linux/amd64" tag-suffix: "-ubi-boringssl" diff --git a/.github/workflows/rebuild-image.yml b/.github/workflows/rebuild-image.yml index 439d10c6e90..12936d5aa71 100644 --- a/.github/workflows/rebuild-image.yml +++ b/.github/workflows/rebuild-image.yml @@ -46,9 +46,9 @@ jobs: build-args: "CGO_ENABLED=0" build-arch: "amd64 arm64" build-platform: "linux/amd64,linux/arm64" - tag-suffix: "-ubi-${{ needs.checkout.outputs.timestamp }}" #ubi + tag-suffix: "-ubi-${{ needs.checkout.outputs.timestamp }}" # ubi - dockerfile: "Dockerfile.ubi" - build-args: "CGO_ENABLED=1 GOEXPERIMENT=boringcrypto" # fips + build-args: "CGO_ENABLED=0 GOEXPERIMENT=boringcrypto" # fips build-arch: "amd64" build-platform: "linux/amd64" tag-suffix: "-ubi-boringssl-${{ needs.checkout.outputs.timestamp }}" From a1f8a8adc7b718b652ba47a3c6991925027c6c2d Mon Sep 17 00:00:00 2001 From: Gustavo Fernandes de Carvalho Date: Wed, 1 Feb 2023 20:30:10 -0300 Subject: [PATCH 09/62] :bug: Fixing PushSecret CRD generation (#1967) * Fixing PushSecret CRD generation Signed-off-by: Gustavo Carvalho * fix: increase hashicorp vault cache size to prevent eviction Also remove tiny cache size from e2e tests Signed-off-by: Moritz Johner --------- Signed-off-by: Gustavo Carvalho Signed-off-by: Moritz Johner Co-authored-by: Moritz Johner --- e2e/framework/addon/eso.go | 4 ---- hack/helm.generate.sh | 4 ++-- pkg/provider/vault/vault.go | 3 ++- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/e2e/framework/addon/eso.go b/e2e/framework/addon/eso.go index 1db2ee45503..4b1b6610b96 100644 --- a/e2e/framework/addon/eso.go +++ b/e2e/framework/addon/eso.go @@ -69,10 +69,6 @@ func NewESO(mutators ...MutationFunc) *ESO { Key: "extraArgs.experimental-enable-aws-session-cache", Value: "true", }, - { - Key: "extraArgs.experimental-vault-token-cache-size", - Value: "10", - }, }, }, } diff --git a/hack/helm.generate.sh b/hack/helm.generate.sh index ab91419d1cc..e759b117ed0 100755 --- a/hack/helm.generate.sh +++ b/hack/helm.generate.sh @@ -21,8 +21,8 @@ for i in "${HELM_DIR}"/templates/crds/*.yml; do cp "$i" "$i.bkp" if [[ "$CRDS_FLAG_NAME" == *"Cluster"* ]]; then echo "{{- if and (.Values.installCRDs) (.Values.crds.$CRDS_FLAG_NAME) }}" > "$i" - elif [[ "$$CRDS_FLAG_NAME" == *"PushSecret"* ]]; then - echo "{{- if and (.Values.installCRDs) (.Values.crds.$$CRDS_FLAG_NAME) }}" > "$$i" + elif [[ "$CRDS_FLAG_NAME" == *"PushSecret"* ]]; then + echo "{{- if and (.Values.installCRDs) (.Values.crds.$CRDS_FLAG_NAME) }}" > "$i" else echo "{{- if .Values.installCRDs }}" > "$i" fi diff --git a/pkg/provider/vault/vault.go b/pkg/provider/vault/vault.go index b0579a49f7b..40110324bb4 100644 --- a/pkg/provider/vault/vault.go +++ b/pkg/provider/vault/vault.go @@ -1400,7 +1400,8 @@ func init() { var vaultTokenCacheSize int fs := pflag.NewFlagSet("vault", pflag.ExitOnError) fs.BoolVar(&enableCache, "experimental-enable-vault-token-cache", false, "Enable experimental Vault token cache. External secrets will reuse the Vault token without creating a new one on each request.") - fs.IntVar(&vaultTokenCacheSize, "experimental-vault-token-cache-size", 100, "Maximum size of Vault token cache. Only used if --experimental-enable-vault-token-cache is set.") + // max. 265k vault leases with 30bytes each ~= 7MB + fs.IntVar(&vaultTokenCacheSize, "experimental-vault-token-cache-size", 2<<17, "Maximum size of Vault token cache. When more tokens than Only used if --experimental-enable-vault-token-cache is set.") lateInit := func() { logger.Info("initializing vault cache with size=%d", vaultTokenCacheSize) clientCache = cache.Must(vaultTokenCacheSize, func(client Client) { From e0a9986ea00318ca62d1b8aaddc5bc778c38afe4 Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Thu, 2 Feb 2023 00:53:27 +0100 Subject: [PATCH 10/62] feat: bump packages (#1976) Signed-off-by: Moritz Johner --- .github/workflows/e2e-managed.yml | 2 +- .github/workflows/e2e.yml | 2 +- e2e/go.mod | 18 ++++++++-------- e2e/go.sum | 36 +++++++++++++++---------------- go.mod | 18 ++++++++-------- go.sum | 36 +++++++++++++++---------------- 6 files changed, 56 insertions(+), 56 deletions(-) diff --git a/.github/workflows/e2e-managed.yml b/.github/workflows/e2e-managed.yml index 785fb351aa9..8fe9a9a82cf 100644 --- a/.github/workflows/e2e-managed.yml +++ b/.github/workflows/e2e-managed.yml @@ -10,7 +10,7 @@ permissions: env: # Common versions GO_VERSION: '1.19' - GINKGO_VERSION: 'v2.1.6' + GINKGO_VERSION: 'v2.8.0' DOCKER_BUILDX_VERSION: 'v0.4.2' # Common users. We can't run a step 'if secrets.GHCR_USERNAME != ""' but we can run diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 61981dfd29a..01b39528501 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -14,7 +14,7 @@ name: e2e tests env: # Common versions GO_VERSION: '1.19' - GINKGO_VERSION: 'v2.1.6' + GINKGO_VERSION: 'v2.8.0' DOCKER_BUILDX_VERSION: 'v0.4.2' KIND_VERSION: 'v0.17.0' KIND_IMAGE: 'kindest/node:v1.26.0' diff --git a/e2e/go.mod b/e2e/go.mod index e2fe1ce8ab3..80171334f10 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -40,20 +40,20 @@ replace ( require ( cloud.google.com/go/secretmanager v1.10.0 github.com/Azure/azure-sdk-for-go v67.3.0+incompatible - github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 + github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 github.com/akeylesslabs/akeyless-go/v2 v2.20.3 - github.com/aliyun/alibaba-cloud-sdk-go v1.62.135 + github.com/aliyun/alibaba-cloud-sdk-go v1.62.146 github.com/argoproj/argo-cd/v2 v2.4.8 - github.com/aws/aws-sdk-go v1.44.175 + github.com/aws/aws-sdk-go v1.44.192 github.com/external-secrets/external-secrets v0.0.0 github.com/fluxcd/helm-controller/api v0.22.2 github.com/fluxcd/pkg/apis/meta v0.14.2 github.com/fluxcd/source-controller/api v0.25.11 github.com/golang-jwt/jwt/v4 v4.4.3 github.com/hashicorp/vault/api v1.8.2 - github.com/onsi/ginkgo/v2 v2.6.1 - github.com/onsi/gomega v1.24.2 + github.com/onsi/ginkgo/v2 v2.8.0 + github.com/onsi/gomega v1.25.0 github.com/oracle/oci-go-sdk/v56 v56.1.0 github.com/xanzy/go-gitlab v0.78.0 golang.org/x/oauth2 v0.3.0 @@ -74,7 +74,7 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.28 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.21 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.22 // indirect github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect @@ -225,11 +225,11 @@ require ( golang.org/x/term v0.4.0 // indirect golang.org/x/text v0.6.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.4.0 // indirect + golang.org/x/tools v0.5.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20221205194025-8222ab48f5fc // indirect - google.golang.org/grpc v1.51.0 // indirect + google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 // indirect + google.golang.org/grpc v1.52.3 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/e2e/go.sum b/e2e/go.sum index 3f3f1f3a222..e98ecdd11bf 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -63,10 +63,10 @@ github.com/Azure/go-autorest/autorest v0.11.28 h1:ndAExarwr5Y+GaHE6VCaY1kyS/HwwG github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/adal v0.9.21 h1:jjQnVFXPfekaqb8vIsv2G1lxshoW+oGv4MDlhRtnYZk= -github.com/Azure/go-autorest/autorest/adal v0.9.21/go.mod h1:zua7mBUaCc5YnSLKYgGJR/w5ePdMDA6H56upLsHzA9U= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 h1:P6bYXFoao05z5uhOQzbC3Qd8JqF3jUoocoTeIxkp2cA= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.11/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= +github.com/Azure/go-autorest/autorest/adal v0.9.22 h1:/GblQdIudfEM3AWWZ0mrYJQSd7JS4S/Mbzh6F0ov0Xc= +github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 h1:wkAZRgT/pn8HhFyzfe9UnqOjJYqlembgCTi72Bm/xKk= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.12/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg= github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 h1:w77/uPk80ZET2F+AfQExZyEWtn+0Rk/uw17m9fv5Ajc= github.com/Azure/go-autorest/autorest/azure/cli v0.4.6/go.mod h1:piCfgPho7BiIDdEQ1+g4VmKyD5y+p/XtSNqE6Hc4QD0= @@ -126,8 +126,8 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI= github.com/alicebob/miniredis/v2 v2.14.2 h1:VeoqKUAsJfT2af61nDE7qhBzqn3J6xjnt9MFAbdrEtg= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.135 h1:KFwOum1maV3qwpBi6R/Zxhcm/7OcweZolDDVSGRLfZU= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.135/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.146 h1:zAH0YjWzonbKHvNkfbxqTmX51uHbkQYu+jJah2IAiCA= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.146/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -159,8 +159,8 @@ github.com/aws/aws-sdk-go v1.33.16/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZve github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= github.com/aws/aws-sdk-go v1.38.49/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.44.175 h1:c0NzHHnPXV5kJoTUFQxFN5cUPpX1SxO635XnwL5/oIY= -github.com/aws/aws-sdk-go v1.44.175/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.192 h1:KL54vCxRd5v5XBGjnF3FelzXXwl+aWHDmDTihFmRNgM= +github.com/aws/aws-sdk-go v1.44.192/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -790,15 +790,15 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.6.1 h1:1xQPCjcqYw/J5LchOcp4/2q/jzJFjiAOc25chhnDw+Q= -github.com/onsi/ginkgo/v2 v2.6.1/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= +github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI= +github.com/onsi/ginkgo/v2 v2.8.0/go.mod h1:6JsQiECmxCa3V5st74AL/AmsV482EDdVrGaVW6z3oYU= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= -github.com/onsi/gomega v1.24.2 h1:J/tulyYK6JwBldPViHJReihxxZ+22FHs0piGjQAvoUE= -github.com/onsi/gomega v1.24.2/go.mod h1:gs3J10IS7Z7r7eXRoNJIrNqU4ToQukCJhFtKrWgHWnk= +github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y= +github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -1449,8 +1449,8 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4= +golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1549,8 +1549,8 @@ google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20221205194025-8222ab48f5fc h1:nUKKji0AarrQKh6XpFEpG3p1TNztxhe7C8TcUvDgXqw= -google.golang.org/genproto v0.0.0-20221205194025-8222ab48f5fc/go.mod h1:1dOng4TWOomJrDGhpXjfCD35wQC6jnC7HpRmOFRqEV0= +google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 h1:p0kMzw6AG0JEzd7Z+kXqOiLhC6gjUQTbtS2zR0Q3DbI= +google.golang.org/genproto v0.0.0-20230131230820-1c016267d619/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1578,8 +1578,8 @@ google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ= +google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/go.mod b/go.mod index 9382b7b5e86..a4e288a0e90 100644 --- a/go.mod +++ b/go.mod @@ -37,8 +37,8 @@ require ( cloud.google.com/go/secretmanager v1.10.0 github.com/Azure/azure-sdk-for-go v67.3.0+incompatible github.com/Azure/go-autorest/autorest v0.11.28 - github.com/Azure/go-autorest/autorest/adal v0.9.21 - github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 + github.com/Azure/go-autorest/autorest/adal v0.9.22 + github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 github.com/IBM/go-sdk-core/v5 v5.12.0 github.com/IBM/secrets-manager-go-sdk v1.0.49 @@ -48,8 +48,8 @@ require ( github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 github.com/akeylesslabs/akeyless-go/v2 v2.20.3 - github.com/aliyun/alibaba-cloud-sdk-go v1.62.135 - github.com/aws/aws-sdk-go v1.44.175 + github.com/aliyun/alibaba-cloud-sdk-go v1.62.146 + github.com/aws/aws-sdk-go v1.44.192 github.com/go-logr/logr v1.2.3 github.com/go-test/deep v1.0.4 // indirect github.com/google/go-cmp v0.5.9 @@ -61,8 +61,8 @@ require ( github.com/hashicorp/vault/api/auth/ldap v0.3.0 github.com/huandu/xstrings v1.3.3 // indirect github.com/lestrrat-go/jwx v1.2.25 - github.com/onsi/ginkgo/v2 v2.6.1 - github.com/onsi/gomega v1.24.2 + github.com/onsi/ginkgo/v2 v2.8.0 + github.com/onsi/gomega v1.25.0 github.com/oracle/oci-go-sdk/v56 v56.1.0 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 @@ -77,8 +77,8 @@ require ( golang.org/x/crypto v0.5.0 golang.org/x/oauth2 v0.3.0 google.golang.org/api v0.103.0 - google.golang.org/genproto v0.0.0-20221205194025-8222ab48f5fc // indirect - google.golang.org/grpc v1.51.0 + google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 // indirect + google.golang.org/grpc v1.52.3 gopkg.in/yaml.v3 v3.0.1 grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 k8s.io/api v0.26.0 @@ -222,7 +222,7 @@ require ( golang.org/x/term v0.4.0 // indirect golang.org/x/text v0.6.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.4.0 // indirect + golang.org/x/tools v0.5.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect diff --git a/go.sum b/go.sum index a208a7fba9c..4fceb2b61b1 100644 --- a/go.sum +++ b/go.sum @@ -62,10 +62,10 @@ github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsC github.com/Azure/go-autorest/autorest v0.11.28 h1:ndAExarwr5Y+GaHE6VCaY1kyS/HwwGGyuimVhWsHOEM= github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA= github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/adal v0.9.21 h1:jjQnVFXPfekaqb8vIsv2G1lxshoW+oGv4MDlhRtnYZk= -github.com/Azure/go-autorest/autorest/adal v0.9.21/go.mod h1:zua7mBUaCc5YnSLKYgGJR/w5ePdMDA6H56upLsHzA9U= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 h1:P6bYXFoao05z5uhOQzbC3Qd8JqF3jUoocoTeIxkp2cA= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.11/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= +github.com/Azure/go-autorest/autorest/adal v0.9.22 h1:/GblQdIudfEM3AWWZ0mrYJQSd7JS4S/Mbzh6F0ov0Xc= +github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 h1:wkAZRgT/pn8HhFyzfe9UnqOjJYqlembgCTi72Bm/xKk= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.12/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg= github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 h1:w77/uPk80ZET2F+AfQExZyEWtn+0Rk/uw17m9fv5Ajc= github.com/Azure/go-autorest/autorest/azure/cli v0.4.6/go.mod h1:piCfgPho7BiIDdEQ1+g4VmKyD5y+p/XtSNqE6Hc4QD0= @@ -118,8 +118,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.135 h1:KFwOum1maV3qwpBi6R/Zxhcm/7OcweZolDDVSGRLfZU= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.135/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.146 h1:zAH0YjWzonbKHvNkfbxqTmX51uHbkQYu+jJah2IAiCA= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.146/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-metrics v0.4.0 h1:yCQqn7dwca4ITXb+CbubHmedzaQYHhNhrEXLYUeEe8Q= @@ -131,8 +131,8 @@ github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:W github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.44.175 h1:c0NzHHnPXV5kJoTUFQxFN5cUPpX1SxO635XnwL5/oIY= -github.com/aws/aws-sdk-go v1.44.175/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.192 h1:KL54vCxRd5v5XBGjnF3FelzXXwl+aWHDmDTihFmRNgM= +github.com/aws/aws-sdk-go v1.44.192/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -556,14 +556,14 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.6.1 h1:1xQPCjcqYw/J5LchOcp4/2q/jzJFjiAOc25chhnDw+Q= -github.com/onsi/ginkgo/v2 v2.6.1/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= +github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI= +github.com/onsi/ginkgo/v2 v2.8.0/go.mod h1:6JsQiECmxCa3V5st74AL/AmsV482EDdVrGaVW6z3oYU= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.0/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/onsi/gomega v1.24.2 h1:J/tulyYK6JwBldPViHJReihxxZ+22FHs0piGjQAvoUE= -github.com/onsi/gomega v1.24.2/go.mod h1:gs3J10IS7Z7r7eXRoNJIrNqU4ToQukCJhFtKrWgHWnk= +github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y= +github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= @@ -1003,8 +1003,8 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4= +golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1091,8 +1091,8 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20221205194025-8222ab48f5fc h1:nUKKji0AarrQKh6XpFEpG3p1TNztxhe7C8TcUvDgXqw= -google.golang.org/genproto v0.0.0-20221205194025-8222ab48f5fc/go.mod h1:1dOng4TWOomJrDGhpXjfCD35wQC6jnC7HpRmOFRqEV0= +google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 h1:p0kMzw6AG0JEzd7Z+kXqOiLhC6gjUQTbtS2zR0Q3DbI= +google.golang.org/genproto v0.0.0-20230131230820-1c016267d619/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -1116,8 +1116,8 @@ google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= -google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ= +google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From fa3acc5fa4553aa56eae3533d47fe58c235dab6b Mon Sep 17 00:00:00 2001 From: Evert Ramos Date: Wed, 1 Feb 2023 20:55:47 -0300 Subject: [PATCH 11/62] Update full-cluster-secret-store.yaml (#1953) Add Oracle provider Signed-off-by: Evert Ramos --- docs/snippets/full-cluster-secret-store.yaml | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/snippets/full-cluster-secret-store.yaml b/docs/snippets/full-cluster-secret-store.yaml index 8ed43403b45..9f8499b3ce5 100644 --- a/docs/snippets/full-cluster-secret-store.yaml +++ b/docs/snippets/full-cluster-secret-store.yaml @@ -99,6 +99,7 @@ spec: key: secret-access-credentials namespace: example projectID: myproject + # (3): Kubernetes provider kubernetes: server: @@ -112,6 +113,28 @@ spec: serviceAccount: name: "example-sa" namespace: "example" + + # (4): Oracle provider + oracle: + # The vault OCID + vault: ocid1.vault.oc1.eu-frankfurt-1.aaa1aaaaaaaaa.aaaaaaaaaaaaaa1aaaaaaa111aaaaaaaaaaaaaaaa + # The vault region + region: eu-frankfurt-1 + auth: + # The user OCID + user: ocid1.user.oc1..aaa1aaaaaaaaa.aaaaaaaaaaaaaa1aaaaaaa111aaaaaaaaaaaaaaaa + # The tenancy OCID + tenancy: ocid1.tenancy.oc1..aaa1aaaaaaaaa.aaaaaaaaaaaaaa1aaaaaaa111aaaaaaaaaaaaaaaa + secretRef: + privatekey: + # The secret that contains your privatekey + name: oci-secret-name + key: privateKey + fingerprint: + # The secret that contains your fingerprint + name: oci-secret-name + key: fingerprint + # (TODO): add more provider examples here # Conditions about namespaces in which the ClusterSecretStore is usable for ExternalSecrets From 6da8b96d4d47275acf72ef1c5281c4525783b93b Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Fri, 3 Feb 2023 13:23:03 +0100 Subject: [PATCH 12/62] :bug: remove ability to call env and expandenv in webhook (#1977) This allows an attacker to exfiltrate environment variables. Signed-off-by: Moritz Johner --- pkg/provider/webhook/webhook.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/provider/webhook/webhook.go b/pkg/provider/webhook/webhook.go index 57bbeb50834..84cc4b8d72b 100644 --- a/pkg/provider/webhook/webhook.go +++ b/pkg/provider/webhook/webhook.go @@ -27,7 +27,6 @@ import ( tpl "text/template" "time" - "github.com/Masterminds/sprig/v3" "github.com/PaesslerAG/jsonpath" "gopkg.in/yaml.v3" corev1 "k8s.io/api/core/v1" @@ -446,7 +445,7 @@ func executeTemplate(tmpl string, data map[string]map[string]string) (bytes.Buff if tmpl == "" { return result, nil } - urlt, err := tpl.New("webhooktemplate").Funcs(sprig.TxtFuncMap()).Funcs(template.FuncMap()).Parse(tmpl) + urlt, err := tpl.New("webhooktemplate").Funcs(template.FuncMap()).Parse(tmpl) if err != nil { return result, err } From 1aef142c63d7d1a394d551601ac0d75ce3c2916a Mon Sep 17 00:00:00 2001 From: Mikhail Advani Date: Fri, 3 Feb 2023 14:45:50 +0100 Subject: [PATCH 13/62] :sparkles: enhance ServiceMonitor configuration (#1973) * Fix #1971 Signed-off-by: mikhailadvani * PR feedback Signed-off-by: mikhailadvani * fix: generate helm docs --------- Signed-off-by: mikhailadvani Co-authored-by: Moritz Johner Co-authored-by: Moritz Johner --- deploy/charts/external-secrets/README.md | 3 +++ .../templates/servicemonitor.yaml | 9 ++++++++ deploy/charts/external-secrets/values.yaml | 21 +++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/deploy/charts/external-secrets/README.md b/deploy/charts/external-secrets/README.md index f0ce109d22e..8759e66d5d2 100644 --- a/deploy/charts/external-secrets/README.md +++ b/deploy/charts/external-secrets/README.md @@ -120,7 +120,10 @@ The command removes all the Kubernetes components associated with the chart and | serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template. | | serviceMonitor.additionalLabels | object | `{}` | Additional labels | | serviceMonitor.enabled | bool | `false` | Specifies whether to create a ServiceMonitor resource for collecting Prometheus metrics | +| serviceMonitor.honorLabels | bool | `false` | Let prometheus add an exported_ prefix to conflicting labels | | serviceMonitor.interval | string | `"30s"` | Interval to scrape metrics | +| serviceMonitor.metricRelabelings | list | `[]` | Metric relabel configs to apply to samples before ingestion. [Metric Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs) | +| serviceMonitor.relabelings | list | `[]` | Relabel configs to apply to samples before ingestion. [Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config) | | serviceMonitor.scrapeTimeout | string | `"25s"` | Timeout if metrics can't be retrieved in given time interval | | tolerations | list | `[]` | | | webhook.affinity | object | `{}` | | diff --git a/deploy/charts/external-secrets/templates/servicemonitor.yaml b/deploy/charts/external-secrets/templates/servicemonitor.yaml index 950507cccd5..b48993a93f7 100644 --- a/deploy/charts/external-secrets/templates/servicemonitor.yaml +++ b/deploy/charts/external-secrets/templates/servicemonitor.yaml @@ -36,4 +36,13 @@ spec: - port: metrics interval: {{ .Values.serviceMonitor.interval }} scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + honorLabels: {{ .Values.serviceMonitor.honorLabels }} + {{- with .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} {{- end }} diff --git a/deploy/charts/external-secrets/values.yaml b/deploy/charts/external-secrets/values.yaml index b82015bc2c7..69aeb1d2da7 100644 --- a/deploy/charts/external-secrets/values.yaml +++ b/deploy/charts/external-secrets/values.yaml @@ -126,6 +126,27 @@ serviceMonitor: # -- Timeout if metrics can't be retrieved in given time interval scrapeTimeout: 25s + # -- Let prometheus add an exported_ prefix to conflicting labels + honorLabels: false + + # -- Metric relabel configs to apply to samples before ingestion. [Metric Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs) + metricRelabelings: [] + # - action: replace + # regex: (.*) + # replacement: $1 + # sourceLabels: + # - exported_namespace + # targetLabel: namespace + + # -- Relabel configs to apply to samples before ingestion. [Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config) + relabelings: [] + # - sourceLabels: [__meta_kubernetes_pod_node_name] + # separator: ; + # regex: ^(.*)$ + # targetLabel: nodename + # replacement: $1 + # action: replace + metrics: service: # -- Enable if you use another monitoring tool than Prometheus to scrape the metrics From ea6cbe2cb47b834c43bc2e3290edaa88f6007b55 Mon Sep 17 00:00:00 2001 From: Marcel Hoyer Date: Fri, 3 Feb 2023 15:06:00 +0100 Subject: [PATCH 14/62] :sparkles: add ability to configure `revisionHistoryLimit` in helm chart (#1979) * feat: add ability to configure `revisionHistoryLimit` for all Deployment resources of the helm chart This enables to turn ReplicaSet revisions off completely, e.g. when deploying ExternalSecrets with GitOps approach. Signed-off-by: Marcel Hoyer * fix: generate helm docs Signed-off-by: Moritz Johner --------- Signed-off-by: Marcel Hoyer Signed-off-by: Moritz Johner Co-authored-by: Moritz Johner Co-authored-by: Moritz Johner --- deploy/charts/external-secrets/README.md | 5 ++++- .../templates/cert-controller-deployment.yaml | 1 + .../external-secrets/templates/deployment.yaml | 1 + .../templates/webhook-deployment.yaml | 1 + deploy/charts/external-secrets/values.yaml | 13 ++++++++++++- 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/deploy/charts/external-secrets/README.md b/deploy/charts/external-secrets/README.md index 8759e66d5d2..c29f33250fe 100644 --- a/deploy/charts/external-secrets/README.md +++ b/deploy/charts/external-secrets/README.md @@ -63,6 +63,7 @@ The command removes all the Kubernetes components associated with the chart and | certController.replicaCount | int | `1` | | | certController.requeueInterval | string | `"5m"` | | | certController.resources | object | `{}` | | +| certController.revisionHistoryLimit | int | `10` | Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) | | certController.securityContext | object | `{}` | | | certController.serviceAccount.annotations | object | `{}` | Annotations to add to the service account. | | certController.serviceAccount.automount | bool | `true` | Automounts the service account token in all containers of the pod | @@ -110,6 +111,7 @@ The command removes all the Kubernetes components associated with the chart and | rbac.create | bool | `true` | Specifies whether role and rolebinding resources should be created. | | replicaCount | int | `1` | | | resources | object | `{}` | | +| revisionHistoryLimit | int | `10` | Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) | | scopedNamespace | string | `""` | If set external secrets are only reconciled in the provided namespace | | scopedRBAC | bool | `false` | Must be used with scopedNamespace. If true, create scoped RBAC roles under the scoped namespace and implicitly disable cluster stores and cluster external secrets | | securityContext | object | `{}` | | @@ -135,7 +137,7 @@ The command removes all the Kubernetes components associated with the chart and | webhook.extraEnv | list | `[]` | | | webhook.extraVolumeMounts | list | `[]` | | | webhook.extraVolumes | list | `[]` | | -| webhook.failurePolicy | string | `"Fail"` | specifies whether validating webhooks should be created with failurePolicy: Fail or Ignore | +| webhook.failurePolicy | string | `"Fail"` | Specifies whether validating webhooks should be created with failurePolicy: Fail or Ignore | | webhook.fullnameOverride | string | `""` | | | webhook.hostNetwork | bool | `false` | Specifies if webhook pod should use hostNetwork or not. | | webhook.image.pullPolicy | string | `"IfNotPresent"` | | @@ -161,6 +163,7 @@ The command removes all the Kubernetes components associated with the chart and | webhook.readinessProbe.port | int | `8081` | ReadinessProbe port for kubelet | | webhook.replicaCount | int | `1` | | | webhook.resources | object | `{}` | | +| webhook.revisionHistoryLimit | int | `10` | Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) | | webhook.secretAnnotations | object | `{}` | Annotations to add to Secret | | webhook.securityContext | object | `{}` | | | webhook.serviceAccount.annotations | object | `{}` | Annotations to add to the service account. | diff --git a/deploy/charts/external-secrets/templates/cert-controller-deployment.yaml b/deploy/charts/external-secrets/templates/cert-controller-deployment.yaml index 3351822a77f..c8d38c2f497 100644 --- a/deploy/charts/external-secrets/templates/cert-controller-deployment.yaml +++ b/deploy/charts/external-secrets/templates/cert-controller-deployment.yaml @@ -12,6 +12,7 @@ metadata: {{- end }} spec: replicas: {{ .Values.certController.replicaCount }} + revisionHistoryLimit: {{ .Values.certController.revisionHistoryLimit }} selector: matchLabels: {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 6 }} diff --git a/deploy/charts/external-secrets/templates/deployment.yaml b/deploy/charts/external-secrets/templates/deployment.yaml index 368867812a3..6c7442de0fa 100644 --- a/deploy/charts/external-secrets/templates/deployment.yaml +++ b/deploy/charts/external-secrets/templates/deployment.yaml @@ -12,6 +12,7 @@ metadata: {{- end }} spec: replicas: {{ .Values.replicaCount }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} selector: matchLabels: {{- include "external-secrets.selectorLabels" . | nindent 6 }} diff --git a/deploy/charts/external-secrets/templates/webhook-deployment.yaml b/deploy/charts/external-secrets/templates/webhook-deployment.yaml index 5b88132486f..853013db564 100644 --- a/deploy/charts/external-secrets/templates/webhook-deployment.yaml +++ b/deploy/charts/external-secrets/templates/webhook-deployment.yaml @@ -12,6 +12,7 @@ metadata: {{- end }} spec: replicas: {{ .Values.webhook.replicaCount }} + revisionHistoryLimit: {{ .Values.webhook.revisionHistoryLimit }} selector: matchLabels: {{- include "external-secrets-webhook.selectorLabels" . | nindent 6 }} diff --git a/deploy/charts/external-secrets/values.yaml b/deploy/charts/external-secrets/values.yaml index 69aeb1d2da7..fe4a6d8fc28 100644 --- a/deploy/charts/external-secrets/values.yaml +++ b/deploy/charts/external-secrets/values.yaml @@ -1,5 +1,8 @@ replicaCount: 1 +# -- Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) +revisionHistoryLimit: 10 + image: repository: ghcr.io/external-secrets/external-secrets pullPolicy: IfNotPresent @@ -181,8 +184,12 @@ webhook: # -- Specifices the lookaheadInterval for certificate validity lookaheadInterval: "" replicaCount: 1 + + # -- Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) + revisionHistoryLimit: 10 + certDir: /tmp/certs - # -- specifies whether validating webhooks should be created with failurePolicy: Fail or Ignore + # -- Specifies whether validating webhooks should be created with failurePolicy: Fail or Ignore failurePolicy: Fail # -- Specifies if webhook pod should use hostNetwork or not. hostNetwork: false @@ -308,6 +315,10 @@ certController: create: true requeueInterval: "5m" replicaCount: 1 + + # -- Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) + revisionHistoryLimit: 10 + image: repository: ghcr.io/external-secrets/external-secrets pullPolicy: IfNotPresent From c2054cc1bf19fee31762ebd8027fea8489ff7727 Mon Sep 17 00:00:00 2001 From: Pedro Parra Ortega Date: Fri, 3 Feb 2023 15:27:21 +0100 Subject: [PATCH 15/62] :sparkles: add-keeper-security-provider (#1768) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add keepersecurity provider Signed-off-by: Pedro Parra Ortega * 🧹chore: bumps (#1758) Signed-off-by: Gustavo Carvalho Signed-off-by: Pedro Parra Ortega * ✨Feature/push secret (#1315) Introduces Push Secret feature with implementations for the following providers: * GCP Secret Manager * AWS Secrets Manager * AWS Parameter Store * Hashicorp Vault KV Signed-off-by: Dominic Meddick Signed-off-by: Amr Fawzy Signed-off-by: William Young Signed-off-by: James Cleveland Signed-off-by: Lilly Daniell Signed-off-by: Adrienne Galloway Signed-off-by: Marcus Dantas Signed-off-by: Gustavo Carvalho Signed-off-by: Nick Ruffles Signed-off-by: Pedro Parra Ortega * Fixing release pipeline for boringssl (#1763) Signed-off-by: Gustavo Carvalho Signed-off-by: Pedro Parra Ortega * chore: bump 0.7.0-rc1 (#1765) Signed-off-by: Gustavo Carvalho Signed-off-by: Pedro Parra Ortega * added documentation Signed-off-by: Pedro Parra Ortega * added pushSecret first iteration Signed-off-by: Pedro Parra Ortega * added pushSecret and updated documentation Signed-off-by: Pedro Parra Ortega * refactor client Signed-off-by: Pedro Parra Ortega * update code and unit tests Signed-off-by: Pedro Parra Ortega * fix code smells Signed-off-by: Pedro Parra Ortega * fix code smells Signed-off-by: Pedro Parra Ortega * fix custom fields Signed-off-by: Pedro Parra Ortega * making it reviewable Signed-off-by: Pedro Parra Ortega * fix custom field on secret map Signed-off-by: Pedro Parra Ortega * Update docs/snippets/keepersecurity-push-secret.yaml Co-authored-by: Moritz Johner Signed-off-by: Pedro Parra Ortega * fixed edge case, improved validation errors and updated docs Signed-off-by: Pedro Parra Ortega * fix logic retrieving secrets Signed-off-by: Pedro Parra Ortega * Update pkg/provider/keepersecurity/client.go Co-authored-by: Moritz Johner Signed-off-by: Pedro Parra Ortega * lint code Signed-off-by: Pedro Parra Ortega * linting code Signed-off-by: Pedro Parra Ortega * go linter fixed Signed-off-by: Pedro Parra Ortega * fix crds and documentation Signed-off-by: Pedro Parra Ortega --------- Signed-off-by: Pedro Parra Ortega Signed-off-by: Gustavo Carvalho Signed-off-by: Dominic Meddick Signed-off-by: Amr Fawzy Signed-off-by: William Young Signed-off-by: James Cleveland Signed-off-by: Lilly Daniell Signed-off-by: Adrienne Galloway Signed-off-by: Marcus Dantas Signed-off-by: Nick Ruffles Signed-off-by: Pedro Parra Ortega Co-authored-by: Pedro Parra Ortega Co-authored-by: Gustavo Fernandes de Carvalho Co-authored-by: Moritz Johner --- .../secretstore_keepersecurity_types.go | 35 + .../v1beta1/secretstore_types.go | 4 + .../v1beta1/zz_generated.deepcopy.go | 45 ++ ...ternal-secrets.io_clustersecretstores.yaml | 126 ++++ .../external-secrets.io_secretstores.yaml | 126 ++++ deploy/crds/bundle.yaml | 176 +++++ docs/api/spec.md | 145 ++++ docs/provider/keeper-security.md | 97 +++ .../keepersecurity-external-secret.yaml | 71 ++ docs/snippets/keepersecurity-push-secret.yaml | 20 + .../snippets/keepersecurity-secret-store.yaml | 26 + go.mod | 1 + go.sum | 2 + hack/api-docs/mkdocs.yml | 1 + pkg/provider/keepersecurity/client.go | 483 +++++++++++++ pkg/provider/keepersecurity/client_test.go | 659 ++++++++++++++++++ pkg/provider/keepersecurity/fake/fake.go | 59 ++ pkg/provider/keepersecurity/provider.go | 204 ++++++ pkg/provider/register/register.go | 1 + 19 files changed, 2281 insertions(+) create mode 100644 apis/externalsecrets/v1beta1/secretstore_keepersecurity_types.go create mode 100644 docs/provider/keeper-security.md create mode 100644 docs/snippets/keepersecurity-external-secret.yaml create mode 100644 docs/snippets/keepersecurity-push-secret.yaml create mode 100644 docs/snippets/keepersecurity-secret-store.yaml create mode 100644 pkg/provider/keepersecurity/client.go create mode 100644 pkg/provider/keepersecurity/client_test.go create mode 100644 pkg/provider/keepersecurity/fake/fake.go create mode 100644 pkg/provider/keepersecurity/provider.go diff --git a/apis/externalsecrets/v1beta1/secretstore_keepersecurity_types.go b/apis/externalsecrets/v1beta1/secretstore_keepersecurity_types.go new file mode 100644 index 00000000000..aa0e6d76c3a --- /dev/null +++ b/apis/externalsecrets/v1beta1/secretstore_keepersecurity_types.go @@ -0,0 +1,35 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import smmeta "github.com/external-secrets/external-secrets/apis/meta/v1" + +// KeeperSecurityProvider Configures a store to sync secrets using Keeper Security. +type KeeperSecurityProvider struct { + Auth *KeeperSecurityAuth `json:"auth"` + + // Keeper Url from which the secrets to be fetched from. + Hostname string `json:"hostname"` + FolderID string `json:"folderID"` +} + +// KeeperSecurityAuth Configuration used to authenticate with KeeperSecurity. +type KeeperSecurityAuth struct { + AppKey smmeta.SecretKeySelector `json:"appKeySecretRef"` + AppOwnerPublicKey smmeta.SecretKeySelector `json:"appOwnerPublicKeySecretRef"` + ClientID smmeta.SecretKeySelector `json:"clientIdSecretRef"` + PrivateKey smmeta.SecretKeySelector `json:"privateKeySecretRef"` + ServerPublicKeyID smmeta.SecretKeySelector `json:"serverPublicKeyIdSecretRef"` +} diff --git a/apis/externalsecrets/v1beta1/secretstore_types.go b/apis/externalsecrets/v1beta1/secretstore_types.go index 39568bc2d8f..caae91fa1c1 100644 --- a/apis/externalsecrets/v1beta1/secretstore_types.go +++ b/apis/externalsecrets/v1beta1/secretstore_types.go @@ -124,6 +124,10 @@ type SecretStoreProvider struct { // Doppler configures this store to sync secrets using the Doppler provider // +optional Doppler *DopplerProvider `json:"doppler,omitempty"` + + // KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider + // +optional + KeeperSecurity *KeeperSecurityProvider `json:"keepersecurity,omitempty"` } type CAProviderType string diff --git a/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go b/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go index 10ba2a3aa2d..08e642f82ba 100644 --- a/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go +++ b/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go @@ -1291,6 +1291,46 @@ func (in *IBMProvider) DeepCopy() *IBMProvider { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeeperSecurityAuth) DeepCopyInto(out *KeeperSecurityAuth) { + *out = *in + in.AppKey.DeepCopyInto(&out.AppKey) + in.AppOwnerPublicKey.DeepCopyInto(&out.AppOwnerPublicKey) + in.ClientID.DeepCopyInto(&out.ClientID) + in.PrivateKey.DeepCopyInto(&out.PrivateKey) + in.ServerPublicKeyID.DeepCopyInto(&out.ServerPublicKeyID) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeeperSecurityAuth. +func (in *KeeperSecurityAuth) DeepCopy() *KeeperSecurityAuth { + if in == nil { + return nil + } + out := new(KeeperSecurityAuth) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeeperSecurityProvider) DeepCopyInto(out *KeeperSecurityProvider) { + *out = *in + if in.Auth != nil { + in, out := &in.Auth, &out.Auth + *out = new(KeeperSecurityAuth) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeeperSecurityProvider. +func (in *KeeperSecurityProvider) DeepCopy() *KeeperSecurityProvider { + if in == nil { + return nil + } + out := new(KeeperSecurityProvider) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KubernetesAuth) DeepCopyInto(out *KubernetesAuth) { *out = *in @@ -1641,6 +1681,11 @@ func (in *SecretStoreProvider) DeepCopyInto(out *SecretStoreProvider) { *out = new(DopplerProvider) (*in).DeepCopyInto(*out) } + if in.KeeperSecurity != nil { + in, out := &in.KeeperSecurity, &out.KeeperSecurity + *out = new(KeeperSecurityProvider) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretStoreProvider. diff --git a/config/crds/bases/external-secrets.io_clustersecretstores.yaml b/config/crds/bases/external-secrets.io_clustersecretstores.yaml index 47a27cfdae1..108e61ff91b 100644 --- a/config/crds/bases/external-secrets.io_clustersecretstores.yaml +++ b/config/crds/bases/external-secrets.io_clustersecretstores.yaml @@ -2363,6 +2363,132 @@ spec: required: - auth type: object + keepersecurity: + description: KeeperSecurity configures this store to sync secrets + using the KeeperSecurity provider + properties: + auth: + description: KeeperSecurityAuth Configuration used to authenticate + with KeeperSecurity. + properties: + appKeySecretRef: + description: A reference to a specific 'key' within a + Secret resource, In some instances, `key` is a required + field. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + appOwnerPublicKeySecretRef: + description: A reference to a specific 'key' within a + Secret resource, In some instances, `key` is a required + field. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + clientIdSecretRef: + description: A reference to a specific 'key' within a + Secret resource, In some instances, `key` is a required + field. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + privateKeySecretRef: + description: A reference to a specific 'key' within a + Secret resource, In some instances, `key` is a required + field. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + serverPublicKeyIdSecretRef: + description: A reference to a specific 'key' within a + Secret resource, In some instances, `key` is a required + field. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + required: + - appKeySecretRef + - appOwnerPublicKeySecretRef + - clientIdSecretRef + - privateKeySecretRef + - serverPublicKeyIdSecretRef + type: object + folderID: + type: string + hostname: + description: Keeper Url from which the secrets to be fetched + from. + type: string + required: + - auth + - folderID + - hostname + type: object kubernetes: description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider diff --git a/config/crds/bases/external-secrets.io_secretstores.yaml b/config/crds/bases/external-secrets.io_secretstores.yaml index 4465dd29918..a4194b9d2fa 100644 --- a/config/crds/bases/external-secrets.io_secretstores.yaml +++ b/config/crds/bases/external-secrets.io_secretstores.yaml @@ -2363,6 +2363,132 @@ spec: required: - auth type: object + keepersecurity: + description: KeeperSecurity configures this store to sync secrets + using the KeeperSecurity provider + properties: + auth: + description: KeeperSecurityAuth Configuration used to authenticate + with KeeperSecurity. + properties: + appKeySecretRef: + description: A reference to a specific 'key' within a + Secret resource, In some instances, `key` is a required + field. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + appOwnerPublicKeySecretRef: + description: A reference to a specific 'key' within a + Secret resource, In some instances, `key` is a required + field. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + clientIdSecretRef: + description: A reference to a specific 'key' within a + Secret resource, In some instances, `key` is a required + field. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + privateKeySecretRef: + description: A reference to a specific 'key' within a + Secret resource, In some instances, `key` is a required + field. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + serverPublicKeyIdSecretRef: + description: A reference to a specific 'key' within a + Secret resource, In some instances, `key` is a required + field. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + required: + - appKeySecretRef + - appOwnerPublicKeySecretRef + - clientIdSecretRef + - privateKeySecretRef + - serverPublicKeyIdSecretRef + type: object + folderID: + type: string + hostname: + description: Keeper Url from which the secrets to be fetched + from. + type: string + required: + - auth + - folderID + - hostname + type: object kubernetes: description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider diff --git a/deploy/crds/bundle.yaml b/deploy/crds/bundle.yaml index 7fdd192e98c..7933ba26fad 100644 --- a/deploy/crds/bundle.yaml +++ b/deploy/crds/bundle.yaml @@ -2173,6 +2173,94 @@ spec: required: - auth type: object + keepersecurity: + description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider + properties: + auth: + description: KeeperSecurityAuth Configuration used to authenticate with KeeperSecurity. + properties: + appKeySecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + appOwnerPublicKeySecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + clientIdSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + privateKeySecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + serverPublicKeyIdSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - appKeySecretRef + - appOwnerPublicKeySecretRef + - clientIdSecretRef + - privateKeySecretRef + - serverPublicKeyIdSecretRef + type: object + folderID: + type: string + hostname: + description: Keeper Url from which the secrets to be fetched from. + type: string + required: + - auth + - folderID + - hostname + type: object kubernetes: description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider properties: @@ -5466,6 +5554,94 @@ spec: required: - auth type: object + keepersecurity: + description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider + properties: + auth: + description: KeeperSecurityAuth Configuration used to authenticate with KeeperSecurity. + properties: + appKeySecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + appOwnerPublicKeySecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + clientIdSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + privateKeySecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + serverPublicKeyIdSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - appKeySecretRef + - appOwnerPublicKeySecretRef + - clientIdSecretRef + - privateKeySecretRef + - serverPublicKeyIdSecretRef + type: object + folderID: + type: string + hostname: + description: Keeper Url from which the secrets to be fetched from. + type: string + required: + - auth + - folderID + - hostname + type: object kubernetes: description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider properties: diff --git a/docs/api/spec.md b/docs/api/spec.md index 90cb6999d00..90a595681dc 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -3425,6 +3425,137 @@ string +

KeeperSecurityAuth +

+

+(Appears on: +KeeperSecurityProvider) +

+

+

KeeperSecurityAuth Configuration used to authenticate with KeeperSecurity.

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+appKeySecretRef
+ + +External Secrets meta/v1.SecretKeySelector + + +
+
+appOwnerPublicKeySecretRef
+ + +External Secrets meta/v1.SecretKeySelector + + +
+
+clientIdSecretRef
+ + +External Secrets meta/v1.SecretKeySelector + + +
+
+privateKeySecretRef
+ + +External Secrets meta/v1.SecretKeySelector + + +
+
+serverPublicKeyIdSecretRef
+ + +External Secrets meta/v1.SecretKeySelector + + +
+
+

KeeperSecurityProvider +

+

+(Appears on: +SecretStoreProvider) +

+

+

KeeperSecurityProvider Configures a store to sync secrets using Keeper Security.

+

+ + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+auth
+ + +KeeperSecurityAuth + + +
+
+hostname
+ +string + +
+

Keeper Url from which the secrets to be fetched from.

+
+folderID
+ +string + +
+

KubernetesAuth

@@ -4306,6 +4437,20 @@ DopplerProvider

Doppler configures this store to sync secrets using the Doppler provider

+ + +keepersecurity
+ + +KeeperSecurityProvider + + + + +(Optional) +

KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider

+ +

SecretStoreRef diff --git a/docs/provider/keeper-security.md b/docs/provider/keeper-security.md new file mode 100644 index 00000000000..0923f078ada --- /dev/null +++ b/docs/provider/keeper-security.md @@ -0,0 +1,97 @@ +## Keeper Security + +External Secrets Operator integrates with [Keeper Security](https://www.keepersecurity.com/) for secret management by using [Keeper Secrets Manager](https://docs.keeper.io/secrets-manager/secrets-manager/about). + + +## Authentication + +### Secrets Manager Configuration (SMC) + +KSM can authenticate using *One Time Access Token* or *Secret Manager Configuration*. In order to work with External Secret Operator we need to configure a Secret Manager Configuration. + +#### Creating Secrets Manager Configuration + +You can find the documentation for the Secret Manager Configuration creation [here](https://docs.keeper.io/secrets-manager/secrets-manager/about/secrets-manager-configuration). Make sure you add the proper permissions to your device in order to be able to read and write secrets + +Once you have created your SMC, you will get a config.json file containing the following keys: +- `hostname` +- `clientId` +- `privateKey` +- `serverPublicKeyId` +- `appKey` +- `appOwnerPublicKey` + +This config will be required to create your secretStores + +## Important note about this documentation +_**The KepeerSecurity calls the entries in vaults 'Records'. These docs use the same term.**_ + +### Update secret store +Be sure the `keepersecurity` provider is listed in the `Kind=SecretStore` + +```yaml +{% include 'keepersecurity-secret-store.yaml' %} +``` + +**NOTE 1:** `folderID` target the folder ID where the secrets should be pushed to. It requires write permissions within the folder +**NOTE 2:** In case of a `ClusterSecretStore`, Be sure to provide `namespace` for `SecretAccessKeyRef` with the namespace of the secret that we just created. + +## External Secrets +### Behavior +* How a Record is equated to an ExternalSecret: + * `remoteRef.key` is equated to a Record's ID + * `remoteRef.property` is equated to one of the following options: + * Fields: [Record's field's Type](https://docs.keeper.io/secrets-manager/secrets-manager/about/field-record-types) + * CustomFields: Record's field's Label + * Files: Record's file's Name + * If empty, defaults to the complete Record in JSON format + * `remoteRef.version` is currently not supported. +* `dataFrom`: + * `find.path` is currently not supported. + * `find.name.regexp` is equated to one of the following options: + * Fields: Record's field's Type + * CustomFields: Record's field's Label + * Files: Record's file's Name + * `find.tags` are not supported at this time. + +### Creating external secret +To create a kubernetes secret from the GCP Secret Manager secret a `Kind=ExternalSecret` is needed. + +```yaml +{% include 'keepersecurity-external-secret.yaml' %} +``` + +The operator will fetch the Keeper Secret Manager secret and inject it as a `Kind=Secret` +``` +kubectl get secret secret-to-be-created -n | -o jsonpath='{.data.dev-secret-test}' | base64 -d +``` + +## Limitations + +There are some limitations using this provider. +* Keeper Secret Manager does not work with `General` Records types nor legacy non-typed records +* Using tags `find.tags` is not supported by KSM +* Using path `find.path` is not supported at the moment + +## Push Secrets + +Push Secret will only work with a custom KeeperSecurity Record type `ExternalSecret` + +### Behavior +* `selector`: + * `secret.name`: name of the kubernetes secret to be pushed +* `data.match`: + * `secretKey`: key on the selected secret to be pushed + * `remoteRef.remoteKey`: Secret and key to be created on the remote provider + * Format: SecretName/SecretKey + +### Creating push secret +To create a Keeper Security record from kubernetes a `Kind=PushSecret` is needed. + +```yaml +{% include 'keepersecurity-push-secret.yaml' %} +``` + +### Limitations +* Only possible to push one key per secret at the moment +* If the record with the selected name exists but the key does not exists the record can not be updated. See [Ability to add custom fields to existing secret #17](https://github.com/Keeper-Security/secrets-manager-go/issues/17) diff --git a/docs/snippets/keepersecurity-external-secret.yaml b/docs/snippets/keepersecurity-external-secret.yaml new file mode 100644 index 00000000000..c68a002f10f --- /dev/null +++ b/docs/snippets/keepersecurity-external-secret.yaml @@ -0,0 +1,71 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: example +spec: + refreshInterval: 1h # rate SecretManager pulls KeeperSrucity + secretStoreRef: + kind: SecretStore + name: example # name of the SecretStore (or kind specified) + target: + name: secret-to-be-created # name of the k8s Secret to be created + creationPolicy: Owner + dataFrom: + - extract: + key: OqPt3Vd37My7G8rTb-8Q # ID of the Keeper Record +--- +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: regcred + namespace: external-secrets +spec: + refreshInterval: 1m + secretStoreRef: + name: keeper + kind: ClusterSecretStore + target: + name: regcred + creationPolicy: Owner + template: + engineVersion: v2 + type: kubernetes.io/dockerconfigjson + data: + .dockerconfigjson: "{\"auths\":{\"registry.example.com\":{\"username\":\"{{ .username }}\",\"password\":\"{{ .password }}\",\"auth\":\"{{(printf \"%s:%s\" .username .password) | b64enc }}\"}}}" + data: + - secretKey: username + remoteRef: + key: OqPt3Vd37My7G8rTb-8Q + property: login + - secretKey: password + remoteRef: + key: OqPt3Vd37My7G8rTb-8Q + property: password +--- +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: config + namespace: external-secrets +spec: + refreshInterval: 1m + secretStoreRef: + name: keeper + kind: ClusterSecretStore + target: + name: credentials + creationPolicy: Owner + template: + engineVersion: v2 + data: + username: "{{ .login }}" + password: "{{ .password }}" + data: + - secretKey: login + remoteRef: + key: OqPt3Vd37My7G8rTb-8Q + property: login + - secretKey: password + remoteRef: + key: OqPt3Vd37My7G8rTb-8Q + property: password diff --git a/docs/snippets/keepersecurity-push-secret.yaml b/docs/snippets/keepersecurity-push-secret.yaml new file mode 100644 index 00000000000..45283e91963 --- /dev/null +++ b/docs/snippets/keepersecurity-push-secret.yaml @@ -0,0 +1,20 @@ +apiVersion: external-secrets.io/v1alpha1 +kind: PushSecret +metadata: + name: example +spec: + secretStoreRefs: + - name: keeper + kind: SecretStore + refreshInterval: "1h" + deletionPolicy: Delete + selector: + secret: + name: secret-name # k8s secret to be pushed + data: + - match: + secretKey: secret-key # k8s key within the secret to be pushed + remoteRef: + remoteKey: remote-secret-name/remote-secret-key # This will create a record called "remote-secret-name" with a key "remote-secret-key" + + diff --git a/docs/snippets/keepersecurity-secret-store.yaml b/docs/snippets/keepersecurity-secret-store.yaml new file mode 100644 index 00000000000..09513bbedf9 --- /dev/null +++ b/docs/snippets/keepersecurity-secret-store.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: external-secrets.io/v1beta1 +kind: SecretStore +metadata: + name: keeper +spec: + provider: + keepersecurity: + hostname: keepersecurity.eu + auth: + appKeySecretRef: + name: keeper-configuration + key: appKey + appOwnerPublicKeySecretRef: + name: keeper-configuration + key: appOwnerPublicKey + privateKeySecretRef: + name: keeper-configuration + key: privateKey + serverPublicKeyIdSecretRef: + name: keeper-configuration + key: serverPublicKeyId + clientIdSecretRef: + name: keeper-configuration + key: clientId + folderID: 1qdsiewFW-U # Folder ID where the secrets can be pushed. It requires write permissions diff --git a/go.mod b/go.mod index a4e288a0e90..532f7ce6a53 100644 --- a/go.mod +++ b/go.mod @@ -96,6 +96,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 github.com/hashicorp/golang-lru v0.5.4 + github.com/keeper-security/secrets-manager-go/core v1.4.0 github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0 github.com/sethvargo/go-password v0.2.0 github.com/spf13/pflag v1.0.5 diff --git a/go.sum b/go.sum index 4fceb2b61b1..fdc9af36a5a 100644 --- a/go.sum +++ b/go.sum @@ -456,6 +456,8 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/keeper-security/secrets-manager-go/core v1.4.0 h1:6x65lMBPwHNirQRXwGByCHrzJx7LDWt06uBUKCLs92w= +github.com/keeper-security/secrets-manager-go/core v1.4.0/go.mod h1:dtlaeeds9+SZsbDAZnQRsDSqEAK9a62SYtqhNql+VgQ= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= diff --git a/hack/api-docs/mkdocs.yml b/hack/api-docs/mkdocs.yml index 61a758513c3..62d76d04a45 100644 --- a/hack/api-docs/mkdocs.yml +++ b/hack/api-docs/mkdocs.yml @@ -95,6 +95,7 @@ nav: - Kubernetes: provider/kubernetes.md - senhasegura DevOps Secrets Management (DSM): provider/senhasegura-dsm.md - Doppler: provider/doppler.md + - Keeper Security: provider/keeper-security.md - Examples: - FluxCD: examples/gitops-using-fluxcd.md - Anchore Engine: examples/anchore-engine-credentials.md diff --git a/pkg/provider/keepersecurity/client.go b/pkg/provider/keepersecurity/client.go new file mode 100644 index 00000000000..9215513da96 --- /dev/null +++ b/pkg/provider/keepersecurity/client.go @@ -0,0 +1,483 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package keepersecurity + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "regexp" + "strings" + + ksm "github.com/keeper-security/secrets-manager-go/core" + "golang.org/x/exp/maps" + + esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" +) + +const ( + errKeeperSecuritySecretsNotFound = "unable to find secrets. %w" + errKeeperSecuritySecretNotFound = "unable to find secret %s. Error: %w" + errKeeperSecuritySecretNotUnique = "more than 1 secret %s found" + errKeeperSecurityNoSecretsFound = "no secrets found" + errKeeperSecurityInvalidSecretInvalidFormat = "invalid secret. Invalid format: %w" + errKeeperSecurityInvalidSecretDuplicatedKey = "invalid Secret. Following keys are duplicated %s" + errKeeperSecurityInvalidProperty = "invalid Property. Secret %s does not have any key matching %s" + errKeeperSecurityInvalidField = "invalid Field. Key %s does not exists" + errKeeperSecurityNoFields = "invalid Secret. Secret %s does not contain any valid field/file" + keeperSecurityFileRef = "fileRef" + keeperSecurityMfa = "oneTimeCode" + errTagsNotImplemented = "'find.tags' is not implemented in the KeeperSecurity provider" + errPathNotImplemented = "'find.path' is not implemented in the KeeperSecurity provider" + errInvalidJSONSecret = "invalid Secret. Secret %s can not be converted to JSON. %w" + errInvalidRegex = "find.name.regex. Invalid Regular expresion %s. %w" + errInvalidRemoteRefKey = "match.remoteRef.remoteKey. Invalid format. Format should match secretName/key got %s" + errInvalidSecretType = "ESO can only push/delete %s record types. Secret %s is type %s" + errFieldNotFound = "secret %s does not contain any custom field with label %s" + + externalSecretType = "externalSecrets" + secretType = "secret" + LoginType = "login" + LoginTypeExpr = "login|username" + PasswordType = "password" + URLTypeExpr = "url|baseurl" + URLType = "url" +) + +type Client struct { + ksmClient SecurityClient + folderID string +} + +type SecurityClient interface { + GetSecrets(filter []string) ([]*ksm.Record, error) + GetSecretByTitle(recordTitle string) (*ksm.Record, error) + CreateSecretWithRecordData(recUID, folderUID string, recordData *ksm.RecordCreate) (string, error) + DeleteSecrets(recrecordUids []string) (map[string]string, error) + Save(record *ksm.Record) error +} + +type Field struct { + Type string `json:"type"` + Value []string `json:"value"` +} + +type CustomField struct { + Type string `json:"type"` + Label string `json:"label"` + Value []string `json:"value"` +} + +type File struct { + Title string `json:"type"` + Content string `json:"content"` +} + +type Secret struct { + Title string `json:"title"` + Type string `json:"type"` + Fields []Field `json:"fields"` + Custom []CustomField `json:"custom"` + Files []File `json:"files"` +} + +func (c *Client) Validate() (esv1beta1.ValidationResult, error) { + return esv1beta1.ValidationResultReady, nil +} + +func (c *Client) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) { + record, err := c.findSecretByID(ref.Key) + if err != nil { + return nil, err + } + secret, err := c.getValidKeeperSecret(record) + if err != nil { + return nil, err + } + + return secret.getItem(ref) +} + +func (c *Client) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) { + record, err := c.findSecretByID(ref.Key) + if err != nil { + return nil, err + } + secret, err := c.getValidKeeperSecret(record) + if err != nil { + return nil, err + } + + return secret.getItems(ref) +} + +func (c *Client) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) { + if ref.Tags != nil { + return nil, fmt.Errorf(errTagsNotImplemented) + } + if ref.Path != nil { + return nil, fmt.Errorf(errPathNotImplemented) + } + secretData := make(map[string][]byte) + records, err := c.findSecrets() + if err != nil { + return nil, err + } + for _, record := range records { + secret, err := c.getValidKeeperSecret(record) + if err != nil { + return nil, err + } + match, err := regexp.MatchString(ref.Name.RegExp, secret.Title) + if err != nil { + return nil, fmt.Errorf(errInvalidRegex, ref.Name.RegExp, err) + } + if !match { + continue + } + secretData[secret.Title], err = secret.getItem(esv1beta1.ExternalSecretDataRemoteRef{}) + if err != nil { + return nil, err + } + } + + return secretData, nil +} + +func (c *Client) Close(ctx context.Context) error { + return nil +} + +func (c *Client) PushSecret(ctx context.Context, value []byte, remoteRef esv1beta1.PushRemoteRef) error { + parts, err := c.buildSecretNameAndKey(remoteRef) + if err != nil { + return err + } + secret, err := c.findSecretByName(parts[0]) + if err != nil { + _, err = c.createSecret(parts[0], parts[1], value) + if err != nil { + return err + } + } + if secret != nil { + if secret.Type() != externalSecretType { + return fmt.Errorf(errInvalidSecretType, externalSecretType, secret.Title(), secret.Type()) + } + err = c.updateSecret(secret, parts[1], value) + if err != nil { + return err + } + } + + return nil +} + +func (c *Client) DeleteSecret(ctx context.Context, remoteRef esv1beta1.PushRemoteRef) error { + parts, err := c.buildSecretNameAndKey(remoteRef) + if err != nil { + return err + } + secret, err := c.findSecretByName(parts[0]) + if err != nil { + return err + } + if secret.Type() != externalSecretType { + return fmt.Errorf(errInvalidSecretType, externalSecretType, secret.Title(), secret.Type()) + } + _, err = c.ksmClient.DeleteSecrets([]string{secret.Uid}) + if err != nil { + return nil + } + + return nil +} + +func (c *Client) buildSecretNameAndKey(remoteRef esv1beta1.PushRemoteRef) ([]string, error) { + parts := strings.Split(remoteRef.GetRemoteKey(), "/") + if len(parts) != 2 { + return nil, fmt.Errorf(errInvalidRemoteRefKey, remoteRef.GetRemoteKey()) + } + + return parts, nil +} + +func (c *Client) createSecret(name, key string, value []byte) (string, error) { + normalizedKey := strings.ToLower(key) + externalSecretRecord := ksm.NewRecordCreate(externalSecretType, name) + login := regexp.MustCompile(LoginTypeExpr) + pass := regexp.MustCompile(PasswordType) + url := regexp.MustCompile(URLTypeExpr) + + switch { + case login.MatchString(normalizedKey): + externalSecretRecord.Fields = append(externalSecretRecord.Fields, + ksm.NewLogin(string(value)), + ) + case pass.MatchString(normalizedKey): + externalSecretRecord.Fields = append(externalSecretRecord.Fields, + ksm.NewPassword(string(value)), + ) + case url.MatchString(normalizedKey): + externalSecretRecord.Fields = append(externalSecretRecord.Fields, + ksm.NewUrl(string(value)), + ) + default: + field := ksm.KeeperRecordField{Type: secretType, Label: key} + externalSecretRecord.Custom = append(externalSecretRecord.Custom, + ksm.Secret{KeeperRecordField: field, Value: []string{string(value)}}, + ) + } + + return c.ksmClient.CreateSecretWithRecordData("", c.folderID, externalSecretRecord) +} + +func (c *Client) updateSecret(secret *ksm.Record, key string, value []byte) error { + normalizedKey := strings.ToLower(key) + login := regexp.MustCompile(LoginTypeExpr) + pass := regexp.MustCompile(PasswordType) + url := regexp.MustCompile(URLTypeExpr) + custom := false + + switch { + case login.MatchString(normalizedKey): + secret.SetFieldValueSingle(LoginType, string(value)) + case pass.MatchString(normalizedKey): + secret.SetPassword(string(value)) + case url.MatchString(normalizedKey): + secret.SetFieldValueSingle(URLType, string(value)) + default: + custom = true + } + if custom { + field := secret.GetCustomFieldValueByLabel(key) + if field != "" { + secret.SetCustomFieldValueSingle(key, string(value)) + } else { + return fmt.Errorf(errFieldNotFound, secret.Title(), key) + } + } + + return c.ksmClient.Save(secret) +} + +func (c *Client) getValidKeeperSecret(secret *ksm.Record) (*Secret, error) { + keeperSecret := Secret{} + err := json.Unmarshal([]byte(secret.RawJson), &keeperSecret) + if err != nil { + return nil, fmt.Errorf(errKeeperSecurityInvalidSecretInvalidFormat, err) + } + keeperSecret.addFiles(secret.Files) + err = keeperSecret.validate() + if err != nil { + return nil, err + } + + return &keeperSecret, nil +} + +func (c *Client) findSecrets() ([]*ksm.Record, error) { + records, err := c.ksmClient.GetSecrets([]string{}) + if err != nil { + return nil, fmt.Errorf(errKeeperSecuritySecretsNotFound, err) + } + + return records, nil +} + +func (c *Client) findSecretByID(id string) (*ksm.Record, error) { + records, err := c.ksmClient.GetSecrets([]string{id}) + if err != nil { + return nil, fmt.Errorf(errKeeperSecuritySecretNotFound, id, err) + } + + if len(records) == 0 { + return nil, errors.New(errKeeperSecurityNoSecretsFound) + } + if len(records) > 1 { + return nil, fmt.Errorf(errKeeperSecuritySecretNotUnique, id) + } + + return records[0], nil +} + +func (c *Client) findSecretByName(name string) (*ksm.Record, error) { + record, err := c.ksmClient.GetSecretByTitle(name) + if err != nil { + return nil, err + } + + return record, nil +} + +func (s *Secret) validate() error { + fields := make(map[string]int) + for _, field := range s.Fields { + fields[field.Type]++ + } + + for _, customField := range s.Custom { + fields[customField.Label]++ + } + + for _, file := range s.Files { + fields[file.Title]++ + } + var duplicates []string + for key, ocurrences := range fields { + if ocurrences > 1 { + duplicates = append(duplicates, key) + } + } + if len(duplicates) != 0 { + return fmt.Errorf(errKeeperSecurityInvalidSecretDuplicatedKey, strings.Join(duplicates, ", ")) + } + + return nil +} + +func (s *Secret) addFiles(keeperFiles []*ksm.KeeperFile) { + for _, f := range keeperFiles { + s.Files = append( + s.Files, + File{ + Title: f.Title, + Content: string(f.GetFileData()), + }, + ) + } +} + +func (s *Secret) getItem(ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) { + if ref.Property != "" { + return s.getProperty(ref.Property) + } + secret, err := s.toString() + + return []byte(secret), err +} + +func (s *Secret) getItems(ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) { + secretData := make(map[string][]byte) + if ref.Property != "" { + value, err := s.getProperty(ref.Property) + if err != nil { + return nil, err + } + secretData[ref.Property] = value + + return secretData, nil + } + + fields := s.getFields() + maps.Copy(secretData, fields) + customFields := s.getCustomFields() + maps.Copy(secretData, customFields) + files := s.getFiles() + maps.Copy(secretData, files) + + if len(secretData) == 0 { + return nil, fmt.Errorf(errKeeperSecurityNoFields, s.Title) + } + + return secretData, nil +} + +func (s *Secret) getField(key string) ([]byte, error) { + for _, field := range s.Fields { + if field.Type == key && field.Type != keeperSecurityFileRef && field.Type != keeperSecurityMfa && len(field.Value) > 0 { + return []byte(field.Value[0]), nil + } + } + + return nil, fmt.Errorf(errKeeperSecurityInvalidField, key) +} + +func (s *Secret) getFields() map[string][]byte { + secretData := make(map[string][]byte) + for _, field := range s.Fields { + if len(field.Value) > 0 { + secretData[field.Type] = []byte(field.Value[0]) + } + } + + return secretData +} + +func (s *Secret) getCustomField(key string) ([]byte, error) { + for _, field := range s.Custom { + if field.Label == key && len(field.Value) > 0 { + return []byte(field.Value[0]), nil + } + } + + return nil, fmt.Errorf(errKeeperSecurityInvalidField, key) +} + +func (s *Secret) getCustomFields() map[string][]byte { + secretData := make(map[string][]byte) + for _, field := range s.Custom { + if len(field.Value) > 0 { + secretData[field.Label] = []byte(field.Value[0]) + } + } + + return secretData +} + +func (s *Secret) getFile(key string) ([]byte, error) { + for _, file := range s.Files { + if file.Title == key { + return []byte(file.Content), nil + } + } + + return nil, fmt.Errorf(errKeeperSecurityInvalidField, key) +} + +func (s *Secret) getProperty(key string) ([]byte, error) { + field, _ := s.getField(key) + if field != nil { + return field, nil + } + customField, _ := s.getCustomField(key) + if customField != nil { + return customField, nil + } + file, _ := s.getFile(key) + if file != nil { + return file, nil + } + + return nil, fmt.Errorf(errKeeperSecurityInvalidProperty, s.Title, key) +} + +func (s *Secret) getFiles() map[string][]byte { + secretData := make(map[string][]byte) + for _, file := range s.Files { + secretData[file.Title] = []byte(file.Content) + } + + return secretData +} + +func (s *Secret) toString() (string, error) { + secretJSON, err := json.Marshal(s) + if err != nil { + return "", fmt.Errorf(errInvalidJSONSecret, s.Title, err) + } + + return string(secretJSON), nil +} diff --git a/pkg/provider/keepersecurity/client_test.go b/pkg/provider/keepersecurity/client_test.go new file mode 100644 index 00000000000..8da3c7048d2 --- /dev/null +++ b/pkg/provider/keepersecurity/client_test.go @@ -0,0 +1,659 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package keepersecurity + +import ( + "context" + "errors" + "fmt" + "reflect" + "testing" + + ksm "github.com/keeper-security/secrets-manager-go/core" + + "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1" + "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" + "github.com/external-secrets/external-secrets/pkg/provider/keepersecurity/fake" +) + +const ( + folderID = "a8ekf031k" + validExistingRecord = "record0/login" + invalidRecord = "record5/login" + outputRecord0 = "{\"title\":\"record0\",\"type\":\"login\",\"fields\":[{\"type\":\"login\",\"value\":[\"foo\"]},{\"type\":\"password\",\"value\":[\"bar\"]}],\"custom\":null,\"files\":null}" + outputRecord1 = "{\"title\":\"record1\",\"type\":\"login\",\"fields\":[{\"type\":\"login\",\"value\":[\"foo\"]},{\"type\":\"password\",\"value\":[\"bar\"]}],\"custom\":null,\"files\":null}" + outputRecord2 = "{\"title\":\"record2\",\"type\":\"login\",\"fields\":[{\"type\":\"login\",\"value\":[\"foo\"]},{\"type\":\"password\",\"value\":[\"bar\"]}],\"custom\":null,\"files\":null}" + record0 = "record0" + record1 = "record1" + record2 = "record2" + LoginKey = "login" + PasswordKey = "password" + RecordNameFormat = "record%d" +) + +func TestClientDeleteSecret(t *testing.T) { + type fields struct { + ksmClient SecurityClient + folderID string + } + type args struct { + ctx context.Context + remoteRef v1beta1.PushRemoteRef + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + { + name: "Delete valid secret", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + DeleteSecretsFn: func(recrecordUids []string) (map[string]string, error) { + return map[string]string{ + record0: record0, + }, nil + }, + GetSecretByTitleFn: func(recordTitle string) (*ksm.Record, error) { + return generateRecords()[0], nil + }, + }, + folderID: folderID, + }, + args: args{ + context.Background(), + &v1alpha1.PushSecretRemoteRef{ + RemoteKey: validExistingRecord, + }, + }, + wantErr: false, + }, + { + name: "Delete invalid secret type", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretByTitleFn: func(recordTitle string) (*ksm.Record, error) { + return generateRecords()[1], nil + }, + }, + folderID: folderID, + }, + args: args{ + context.Background(), + &v1alpha1.PushSecretRemoteRef{ + RemoteKey: validExistingRecord, + }, + }, + wantErr: true, + }, + { + name: "Delete non existing secret", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretByTitleFn: func(recordTitle string) (*ksm.Record, error) { + return nil, errors.New("failed") + }, + }, + folderID: folderID, + }, + args: args{ + context.Background(), + &v1alpha1.PushSecretRemoteRef{ + RemoteKey: invalidRecord, + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &Client{ + ksmClient: tt.fields.ksmClient, + folderID: tt.fields.folderID, + } + if err := c.DeleteSecret(tt.args.ctx, tt.args.remoteRef); (err != nil) != tt.wantErr { + t.Errorf("DeleteSecret() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestClientGetAllSecrets(t *testing.T) { + type fields struct { + ksmClient SecurityClient + folderID string + } + type args struct { + ctx context.Context + ref v1beta1.ExternalSecretFind + } + var path = "path_to_fail" + tests := []struct { + name string + fields fields + args args + want map[string][]byte + wantErr bool + }{ + { + name: "Tags not Implemented", + fields: fields{ + ksmClient: &fake.MockKeeperClient{}, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + ref: v1beta1.ExternalSecretFind{ + Tags: map[string]string{ + "xxx": "yyy", + }, + }, + }, + wantErr: true, + }, + { + name: "Path not Implemented", + fields: fields{ + ksmClient: &fake.MockKeeperClient{}, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + ref: v1beta1.ExternalSecretFind{ + Path: &path, + }, + }, + wantErr: true, + }, + { + name: "Get secrets with matching regex", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretsFn: func(strings []string) ([]*ksm.Record, error) { + return generateRecords(), nil + }, + }, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + ref: v1beta1.ExternalSecretFind{ + Name: &v1beta1.FindName{ + RegExp: "record", + }, + }, + }, + want: map[string][]byte{ + record0: []byte(outputRecord0), + record1: []byte(outputRecord1), + record2: []byte(outputRecord2), + }, + wantErr: false, + }, + { + name: "Get 1 secret with matching regex", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretsFn: func(strings []string) ([]*ksm.Record, error) { + return generateRecords(), nil + }, + }, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + ref: v1beta1.ExternalSecretFind{ + Name: &v1beta1.FindName{ + RegExp: record0, + }, + }, + }, + want: map[string][]byte{ + record0: []byte(outputRecord0), + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &Client{ + ksmClient: tt.fields.ksmClient, + folderID: tt.fields.folderID, + } + got, err := c.GetAllSecrets(tt.args.ctx, tt.args.ref) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllSecrets() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllSecrets() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestClientGetSecret(t *testing.T) { + type fields struct { + ksmClient SecurityClient + folderID string + } + type args struct { + ctx context.Context + ref v1beta1.ExternalSecretDataRemoteRef + } + tests := []struct { + name string + fields fields + args args + want []byte + wantErr bool + }{ + { + name: "Get Secret with a property", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretsFn: func(filter []string) ([]*ksm.Record, error) { + return []*ksm.Record{generateRecords()[0]}, nil + }, + }, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + ref: v1beta1.ExternalSecretDataRemoteRef{ + Key: record0, + Property: LoginKey, + }, + }, + want: []byte("foo"), + wantErr: false, + }, + { + name: "Get Secret without property", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretsFn: func(filter []string) ([]*ksm.Record, error) { + return []*ksm.Record{generateRecords()[0]}, nil + }, + }, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + ref: v1beta1.ExternalSecretDataRemoteRef{ + Key: record0, + }, + }, + want: []byte(outputRecord0), + wantErr: false, + }, + { + name: "Get non existing secret", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretsFn: func(filter []string) ([]*ksm.Record, error) { + return nil, errors.New("not found") + }, + }, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + ref: v1beta1.ExternalSecretDataRemoteRef{ + Key: "record5", + }, + }, + wantErr: true, + }, + { + name: "Get valid secret with non existing property", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretsFn: func(filter []string) ([]*ksm.Record, error) { + return []*ksm.Record{generateRecords()[0]}, nil + }, + }, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + ref: v1beta1.ExternalSecretDataRemoteRef{ + Key: record0, + Property: "invalid", + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &Client{ + ksmClient: tt.fields.ksmClient, + folderID: tt.fields.folderID, + } + got, err := c.GetSecret(tt.args.ctx, tt.args.ref) + if (err != nil) != tt.wantErr { + t.Errorf("GetSecret() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetSecret() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestClientGetSecretMap(t *testing.T) { + type fields struct { + ksmClient SecurityClient + folderID string + } + type args struct { + ctx context.Context + ref v1beta1.ExternalSecretDataRemoteRef + } + tests := []struct { + name string + fields fields + args args + want map[string][]byte + wantErr bool + }{ + { + name: "Get Secret with valid property", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretsFn: func(filter []string) ([]*ksm.Record, error) { + return []*ksm.Record{generateRecords()[0]}, nil + }, + }, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + ref: v1beta1.ExternalSecretDataRemoteRef{ + Key: record0, + Property: LoginKey, + }, + }, + want: map[string][]byte{ + LoginKey: []byte("foo"), + }, + wantErr: false, + }, + { + name: "Get Secret without property", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretsFn: func(filter []string) ([]*ksm.Record, error) { + return []*ksm.Record{generateRecords()[0]}, nil + }, + }, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + ref: v1beta1.ExternalSecretDataRemoteRef{ + Key: record0, + }, + }, + want: map[string][]byte{ + LoginKey: []byte("foo"), + PasswordKey: []byte("bar"), + }, + wantErr: false, + }, + { + name: "Get non existing secret", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretsFn: func(filter []string) ([]*ksm.Record, error) { + return nil, errors.New("not found") + }, + }, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + ref: v1beta1.ExternalSecretDataRemoteRef{ + Key: "record5", + }, + }, + wantErr: true, + }, + { + name: "Get Secret with invalid property", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretsFn: func(filter []string) ([]*ksm.Record, error) { + return []*ksm.Record{generateRecords()[0]}, nil + }, + }, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + ref: v1beta1.ExternalSecretDataRemoteRef{ + Key: record0, + Property: "invalid", + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &Client{ + ksmClient: tt.fields.ksmClient, + folderID: tt.fields.folderID, + } + got, err := c.GetSecretMap(tt.args.ctx, tt.args.ref) + if (err != nil) != tt.wantErr { + t.Errorf("GetSecretMap() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetSecretMap() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestClientPushSecret(t *testing.T) { + type fields struct { + ksmClient SecurityClient + folderID string + } + type args struct { + ctx context.Context + value []byte + remoteRef v1beta1.PushRemoteRef + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + { + name: "Invalid remote ref", + fields: fields{ + ksmClient: &fake.MockKeeperClient{}, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + remoteRef: v1alpha1.PushSecretRemoteRef{ + RemoteKey: record0, + }, + value: []byte("foo"), + }, + wantErr: true, + }, + { + name: "Push new valid secret", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretByTitleFn: func(recordTitle string) (*ksm.Record, error) { + return nil, errors.New("NotFound") + }, + CreateSecretWithRecordDataFn: func(recUID, folderUid string, recordData *ksm.RecordCreate) (string, error) { + return "record5", nil + }, + }, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + remoteRef: v1alpha1.PushSecretRemoteRef{ + RemoteKey: invalidRecord, + }, + value: []byte("foo"), + }, + wantErr: false, + }, + { + name: "Push existing valid secret", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretByTitleFn: func(recordTitle string) (*ksm.Record, error) { + return generateRecords()[0], nil + }, + SaveFn: func(record *ksm.Record) error { + return nil + }, + }, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + remoteRef: v1alpha1.PushSecretRemoteRef{ + RemoteKey: validExistingRecord, + }, + value: []byte("foo2"), + }, + wantErr: false, + }, + { + name: "Push existing invalid secret", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretByTitleFn: func(recordTitle string) (*ksm.Record, error) { + return generateRecords()[1], nil + }, + SaveFn: func(record *ksm.Record) error { + return nil + }, + }, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + remoteRef: v1alpha1.PushSecretRemoteRef{ + RemoteKey: validExistingRecord, + }, + value: []byte("foo2"), + }, + wantErr: true, + }, + { + name: "Unable to push new valid secret", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretByTitleFn: func(recordTitle string) (*ksm.Record, error) { + return nil, errors.New("NotFound") + }, + CreateSecretWithRecordDataFn: func(recUID, folderUID string, recordData *ksm.RecordCreate) (string, error) { + return "", errors.New("Unable to push") + }, + }, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + remoteRef: v1alpha1.PushSecretRemoteRef{ + RemoteKey: invalidRecord, + }, + value: []byte("foo"), + }, + wantErr: true, + }, + { + name: "Unable to save existing valid secret", + fields: fields{ + ksmClient: &fake.MockKeeperClient{ + GetSecretByTitleFn: func(recordTitle string) (*ksm.Record, error) { + return generateRecords()[0], nil + }, + SaveFn: func(record *ksm.Record) error { + return errors.New("Unable to save") + }, + }, + folderID: folderID, + }, + args: args{ + ctx: context.Background(), + remoteRef: v1alpha1.PushSecretRemoteRef{ + RemoteKey: validExistingRecord, + }, + value: []byte("foo2"), + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &Client{ + ksmClient: tt.fields.ksmClient, + folderID: tt.fields.folderID, + } + if err := c.PushSecret(tt.args.ctx, tt.args.value, tt.args.remoteRef); (err != nil) != tt.wantErr { + t.Errorf("PushSecret() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func generateRecords() []*ksm.Record { + var records []*ksm.Record + for i := 0; i < 3; i++ { + var record ksm.Record + if i == 0 { + record = ksm.Record{ + Uid: fmt.Sprintf(RecordNameFormat, i), + RecordDict: map[string]interface{}{ + "type": externalSecretType, + "folderUID": folderID, + }, + } + } else { + record = ksm.Record{ + Uid: fmt.Sprintf(RecordNameFormat, i), + RecordDict: map[string]interface{}{ + "type": LoginType, + "folderUID": folderID, + }, + } + } + sec := fmt.Sprintf("{\"title\":\"record%d\",\"type\":\"login\",\"fields\":[{\"type\":\"login\",\"value\":[\"foo\"]},{\"type\":\"password\",\"value\":[\"bar\"]}]}", i) + record.SetTitle(fmt.Sprintf(RecordNameFormat, i)) + record.SetStandardFieldValue(LoginKey, "foo") + record.SetStandardFieldValue(PasswordKey, "bar") + record.RawJson = sec + records = append(records, &record) + } + + return records +} diff --git a/pkg/provider/keepersecurity/fake/fake.go b/pkg/provider/keepersecurity/fake/fake.go new file mode 100644 index 00000000000..91a0b10041b --- /dev/null +++ b/pkg/provider/keepersecurity/fake/fake.go @@ -0,0 +1,59 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package fake + +import ksm "github.com/keeper-security/secrets-manager-go/core" + +type MockKeeperClient struct { + GetSecretsFn func([]string) ([]*ksm.Record, error) + GetSecretByTitleFn func(recordTitle string) (*ksm.Record, error) + CreateSecretWithRecordDataFn func(recUID, folderUID string, recordData *ksm.RecordCreate) (string, error) + DeleteSecretsFn func(recrecordUids []string) (map[string]string, error) + SaveFn func(record *ksm.Record) error +} + +type GetSecretsMockReturn struct { + Secrets []*ksm.Record + Err error +} + +type GetSecretsByTitleMockReturn struct { + Secret *ksm.Record + Err error +} + +type CreateSecretWithRecordDataMockReturn struct { + ID string + Err error +} + +func (mc *MockKeeperClient) GetSecrets(filter []string) ([]*ksm.Record, error) { + return mc.GetSecretsFn(filter) +} + +func (mc *MockKeeperClient) GetSecretByTitle(recordTitle string) (*ksm.Record, error) { + return mc.GetSecretByTitleFn(recordTitle) +} + +func (mc *MockKeeperClient) CreateSecretWithRecordData(recUID, folderUID string, recordData *ksm.RecordCreate) (string, error) { + return mc.CreateSecretWithRecordDataFn(recUID, folderUID, recordData) +} + +func (mc *MockKeeperClient) DeleteSecrets(recrecordUids []string) (map[string]string, error) { + return mc.DeleteSecretsFn(recrecordUids) +} + +func (mc *MockKeeperClient) Save(record *ksm.Record) error { + return mc.SaveFn(record) +} diff --git a/pkg/provider/keepersecurity/provider.go b/pkg/provider/keepersecurity/provider.go new file mode 100644 index 00000000000..c88ccf0905a --- /dev/null +++ b/pkg/provider/keepersecurity/provider.go @@ -0,0 +1,204 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package keepersecurity + +import ( + "context" + "fmt" + "net/url" + + ksm "github.com/keeper-security/secrets-manager-go/core" + "github.com/keeper-security/secrets-manager-go/core/logger" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + kclient "sigs.k8s.io/controller-runtime/pkg/client" + + esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" + smmeta "github.com/external-secrets/external-secrets/apis/meta/v1" + "github.com/external-secrets/external-secrets/pkg/utils" +) + +const ( + errKeeperSecurityUnableToCreateConfig = "unable to create valid KeeperSecurity config: %w" + errKeeperSecurityStore = "received invalid KeeperSecurity SecretStore resource: %s" + errKeeperSecurityNilSpec = "nil spec" + errKeeperSecurityNilSpecProvider = "nil spec.provider" + errKeeperSecurityNilSpecProviderKeeperSecurity = "nil spec.provider.keepersecurity" + errKeeperSecurityStoreMissingAuth = "missing: spec.provider.keepersecurity.auth" + errKeeperSecurityStoreMissingAppKey = "missing: spec.provider.keepersecurity.auth.appKeySecretRef %w" + errKeeperSecurityStoreMissingAppOwnerPublicKey = "missing: spec.provider.keepersecurity.auth.appOwnerPublicKeySecretRef %w" + errKeeperSecurityStoreMissingClientID = "missing: spec.provider.keepersecurity.auth.clientIdSecretRef %w" + errKeeperSecurityStoreMissingPrivateKey = "missing: spec.provider.keepersecurity.auth.privateKeySecretRef %w" + errKeeperSecurityStoreMissingServerPublicKeyID = "missing: spec.provider.keepersecurity.auth.serverPublicKeyIDSecretRef %w" + errKeeperSecurityStoreInvalidConnectHost = "unable to parse URL: spec.provider.keepersecurity.connectHost: %w" + errInvalidClusterStoreMissingK8sSecretNamespace = "invalid ClusterSecretStore: missing KeeperSecurity k8s Auth Secret Namespace" + errFetchK8sSecret = "could not fetch k8s Secret: %w" + errMissingK8sSecretKey = "missing Secret key: %s" +) + +// Provider implements the necessary NewClient() and ValidateStore() funcs. +type Provider struct{} + +// https://github.com/external-secrets/external-secrets/issues/644 +var _ esv1beta1.SecretsClient = &Client{} +var _ esv1beta1.Provider = &Provider{} + +func init() { + esv1beta1.Register(&Provider{}, &esv1beta1.SecretStoreProvider{ + KeeperSecurity: &esv1beta1.KeeperSecurityProvider{}, + }) +} + +func (p *Provider) Capabilities() esv1beta1.SecretStoreCapabilities { + return esv1beta1.SecretStoreReadWrite +} + +// NewClient constructs a GCP Provider. +func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, namespace string) (esv1beta1.SecretsClient, error) { + storeSpec := store.GetSpec() + if storeSpec == nil || storeSpec.Provider == nil || storeSpec.Provider.KeeperSecurity == nil { + return nil, fmt.Errorf(errKeeperSecurityStore, store) + } + + keeperStore := storeSpec.Provider.KeeperSecurity + + isClusterKind := store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind + clientConfig, err := getKeeperSecurityConfig(ctx, keeperStore, kube, isClusterKind, namespace) + if err != nil { + return nil, fmt.Errorf(errKeeperSecurityUnableToCreateConfig, err) + } + ksmClientOptions := &ksm.ClientOptions{ + Config: ksm.NewMemoryKeyValueStorage(clientConfig), + LogLevel: logger.ErrorLevel, + } + ksmClient := ksm.NewSecretsManager(ksmClientOptions) + client := &Client{ + folderID: keeperStore.FolderID, + ksmClient: ksmClient, + } + + return client, nil +} + +func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error { + if store == nil { + return fmt.Errorf(errKeeperSecurityStore, store) + } + spc := store.GetSpec() + if spc == nil { + return fmt.Errorf(errKeeperSecurityNilSpec) + } + if spc.Provider == nil { + return fmt.Errorf(errKeeperSecurityNilSpecProvider) + } + if spc.Provider.KeeperSecurity == nil { + return fmt.Errorf(errKeeperSecurityNilSpecProviderKeeperSecurity) + } + + // check mandatory fields + config := spc.Provider.KeeperSecurity + + // check valid URL + if _, err := url.Parse(config.Hostname); err != nil { + return fmt.Errorf(errKeeperSecurityStoreInvalidConnectHost, err) + } + + if config.Auth == nil { + return fmt.Errorf(errKeeperSecurityStoreMissingAuth) + } + + if err := utils.ValidateSecretSelector(store, config.Auth.AppKey); err != nil { + return fmt.Errorf(errKeeperSecurityStoreMissingAppKey, err) + } + + if err := utils.ValidateSecretSelector(store, config.Auth.AppOwnerPublicKey); err != nil { + return fmt.Errorf(errKeeperSecurityStoreMissingAppOwnerPublicKey, err) + } + + if err := utils.ValidateSecretSelector(store, config.Auth.PrivateKey); err != nil { + return fmt.Errorf(errKeeperSecurityStoreMissingPrivateKey, err) + } + + if err := utils.ValidateSecretSelector(store, config.Auth.ClientID); err != nil { + return fmt.Errorf(errKeeperSecurityStoreMissingClientID, err) + } + + if err := utils.ValidateSecretSelector(store, config.Auth.ServerPublicKeyID); err != nil { + return fmt.Errorf(errKeeperSecurityStoreMissingServerPublicKeyID, err) + } + + return nil +} + +func getKeeperSecurityConfig(ctx context.Context, store *esv1beta1.KeeperSecurityProvider, kube kclient.Client, isClusterKind bool, namespace string) (map[string]string, error) { + auth := store.Auth + apiKey, err := getAuthParameter(ctx, auth.AppKey, kube, isClusterKind, namespace) + if err != nil { + return nil, err + } + appOwnerPublicKey, err := getAuthParameter(ctx, auth.AppOwnerPublicKey, kube, isClusterKind, namespace) + if err != nil { + return nil, err + } + clientID, err := getAuthParameter(ctx, auth.ClientID, kube, isClusterKind, namespace) + if err != nil { + return nil, err + } + privateKey, err := getAuthParameter(ctx, auth.PrivateKey, kube, isClusterKind, namespace) + if err != nil { + return nil, err + } + serverPublicKeyID, err := getAuthParameter(ctx, auth.ServerPublicKeyID, kube, isClusterKind, namespace) + if err != nil { + return nil, err + } + + return map[string]string{ + "appKey": apiKey, + "appOwnerPublicKey": appOwnerPublicKey, + "clientId": clientID, + "hostname": store.Hostname, + "privateKey": privateKey, + "serverPublicKeyID": serverPublicKeyID, + }, nil +} + +func getAuthParameter(ctx context.Context, param smmeta.SecretKeySelector, kube kclient.Client, isClusterKind bool, namespace string) (string, error) { + credentialsSecret := &v1.Secret{} + credentialsSecretName := param.Name + objectKey := types.NamespacedName{ + Name: credentialsSecretName, + Namespace: namespace, + } + + // only ClusterStore is allowed to set namespace (and then it's required) + if isClusterKind { + if credentialsSecretName != "" && param.Namespace == nil { + return "", fmt.Errorf(errInvalidClusterStoreMissingK8sSecretNamespace) + } else if credentialsSecretName != "" { + objectKey.Namespace = *param.Namespace + } + } + + err := kube.Get(ctx, objectKey, credentialsSecret) + if err != nil { + return "", fmt.Errorf(errFetchK8sSecret, err) + } + data := credentialsSecret.Data[param.Key] + if (data == nil) || (len(data) == 0) { + return "", fmt.Errorf(errMissingK8sSecretKey, param.Key) + } + + return string(data), nil +} diff --git a/pkg/provider/register/register.go b/pkg/provider/register/register.go index 2c04637847c..cd9c0fb0b19 100644 --- a/pkg/provider/register/register.go +++ b/pkg/provider/register/register.go @@ -26,6 +26,7 @@ import ( _ "github.com/external-secrets/external-secrets/pkg/provider/gcp/secretmanager" _ "github.com/external-secrets/external-secrets/pkg/provider/gitlab" _ "github.com/external-secrets/external-secrets/pkg/provider/ibm" + _ "github.com/external-secrets/external-secrets/pkg/provider/keepersecurity" _ "github.com/external-secrets/external-secrets/pkg/provider/kubernetes" _ "github.com/external-secrets/external-secrets/pkg/provider/onepassword" _ "github.com/external-secrets/external-secrets/pkg/provider/oracle" From e72f37129475ca4419ffbb8df62eb81394b39d99 Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Fri, 3 Feb 2023 19:10:56 +0100 Subject: [PATCH 16/62] :bug: fix panic when using jwt without secretRef/saRef (#1980) Fixes #1957 Signed-off-by: Moritz Johner --- pkg/provider/akeyless/akeyless_api.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkg/provider/akeyless/akeyless_api.go b/pkg/provider/akeyless/akeyless_api.go index dd1a6844555..f2bec119081 100644 --- a/pkg/provider/akeyless/akeyless_api.go +++ b/pkg/provider/akeyless/akeyless_api.go @@ -249,7 +249,7 @@ func (a *akeylessBase) getCloudID(provider, accTypeParam string) (string, error) } func (a *akeylessBase) getK8SServiceAccountJWT(ctx context.Context, kubernetesAuth *esv1beta1.AkeylessKubernetesAuth) (string, error) { - if kubernetesAuth.ServiceAccountRef != nil { + if kubernetesAuth != nil && kubernetesAuth.ServiceAccountRef != nil { // Kubernetes Date: Tue, 7 Feb 2023 14:08:01 +0100 Subject: [PATCH 17/62] :broom: bump dependencies & regenerate CRDs (#1990) Signed-off-by: Moritz Johner --- Dockerfile.standalone | 2 +- ...nal-secrets.io_clusterexternalsecrets.yaml | 2 +- ...ternal-secrets.io_clustersecretstores.yaml | 2 +- .../external-secrets.io_externalsecrets.yaml | 2 +- .../external-secrets.io_pushsecrets.yaml | 2 +- .../external-secrets.io_secretstores.yaml | 2 +- ...s.external-secrets.io_acraccesstokens.yaml | 2 +- ...nal-secrets.io_ecrauthorizationtokens.yaml | 2 +- .../generators.external-secrets.io_fakes.yaml | 2 +- ...s.external-secrets.io_gcraccesstokens.yaml | 2 +- ...erators.external-secrets.io_passwords.yaml | 2 +- deploy/crds/bundle.yaml | 20 +- e2e/go.mod | 82 +++--- e2e/go.sum | 144 +++++----- go.mod | 118 ++++----- go.sum | 247 ++++++++---------- 16 files changed, 305 insertions(+), 328 deletions(-) diff --git a/Dockerfile.standalone b/Dockerfile.standalone index d6f7c600e36..7f4c5a9641f 100644 --- a/Dockerfile.standalone +++ b/Dockerfile.standalone @@ -1,6 +1,6 @@ # This version of Dockerfile is for building without external dependencies. # Build a multi-platform image e.g. `docker buildx build --push --platform linux/arm64,linux/amd64 --tag external-secrets:dev --file Dockerfile.standalone .` -FROM golang:1.19.5-alpine AS builder +FROM golang:1.20.0-alpine AS builder ARG TARGETOS ARG TARGETARCH ENV CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} diff --git a/config/crds/bases/external-secrets.io_clusterexternalsecrets.yaml b/config/crds/bases/external-secrets.io_clusterexternalsecrets.yaml index e54bd78ca00..87a266a229a 100644 --- a/config/crds/bases/external-secrets.io_clusterexternalsecrets.yaml +++ b/config/crds/bases/external-secrets.io_clusterexternalsecrets.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: clusterexternalsecrets.external-secrets.io spec: diff --git a/config/crds/bases/external-secrets.io_clustersecretstores.yaml b/config/crds/bases/external-secrets.io_clustersecretstores.yaml index 108e61ff91b..662655f014e 100644 --- a/config/crds/bases/external-secrets.io_clustersecretstores.yaml +++ b/config/crds/bases/external-secrets.io_clustersecretstores.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: clustersecretstores.external-secrets.io spec: diff --git a/config/crds/bases/external-secrets.io_externalsecrets.yaml b/config/crds/bases/external-secrets.io_externalsecrets.yaml index e39e6b44c01..0f00baa3103 100644 --- a/config/crds/bases/external-secrets.io_externalsecrets.yaml +++ b/config/crds/bases/external-secrets.io_externalsecrets.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: externalsecrets.external-secrets.io spec: diff --git a/config/crds/bases/external-secrets.io_pushsecrets.yaml b/config/crds/bases/external-secrets.io_pushsecrets.yaml index 70a01c742c1..d23db6cdff0 100644 --- a/config/crds/bases/external-secrets.io_pushsecrets.yaml +++ b/config/crds/bases/external-secrets.io_pushsecrets.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: pushsecrets.external-secrets.io spec: diff --git a/config/crds/bases/external-secrets.io_secretstores.yaml b/config/crds/bases/external-secrets.io_secretstores.yaml index a4194b9d2fa..1bf196e4eec 100644 --- a/config/crds/bases/external-secrets.io_secretstores.yaml +++ b/config/crds/bases/external-secrets.io_secretstores.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: secretstores.external-secrets.io spec: diff --git a/config/crds/bases/generators.external-secrets.io_acraccesstokens.yaml b/config/crds/bases/generators.external-secrets.io_acraccesstokens.yaml index 9e52cba88cb..a4b0b979e17 100644 --- a/config/crds/bases/generators.external-secrets.io_acraccesstokens.yaml +++ b/config/crds/bases/generators.external-secrets.io_acraccesstokens.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: acraccesstokens.generators.external-secrets.io spec: diff --git a/config/crds/bases/generators.external-secrets.io_ecrauthorizationtokens.yaml b/config/crds/bases/generators.external-secrets.io_ecrauthorizationtokens.yaml index 00b068ea202..a5606400f6c 100644 --- a/config/crds/bases/generators.external-secrets.io_ecrauthorizationtokens.yaml +++ b/config/crds/bases/generators.external-secrets.io_ecrauthorizationtokens.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: ecrauthorizationtokens.generators.external-secrets.io spec: diff --git a/config/crds/bases/generators.external-secrets.io_fakes.yaml b/config/crds/bases/generators.external-secrets.io_fakes.yaml index 233f21f59d0..5efbf0813be 100644 --- a/config/crds/bases/generators.external-secrets.io_fakes.yaml +++ b/config/crds/bases/generators.external-secrets.io_fakes.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: fakes.generators.external-secrets.io spec: diff --git a/config/crds/bases/generators.external-secrets.io_gcraccesstokens.yaml b/config/crds/bases/generators.external-secrets.io_gcraccesstokens.yaml index 0ac9e43687c..f29bf661e0f 100644 --- a/config/crds/bases/generators.external-secrets.io_gcraccesstokens.yaml +++ b/config/crds/bases/generators.external-secrets.io_gcraccesstokens.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: gcraccesstokens.generators.external-secrets.io spec: diff --git a/config/crds/bases/generators.external-secrets.io_passwords.yaml b/config/crds/bases/generators.external-secrets.io_passwords.yaml index 2278f8ebda8..12e53c3b9a4 100644 --- a/config/crds/bases/generators.external-secrets.io_passwords.yaml +++ b/config/crds/bases/generators.external-secrets.io_passwords.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: passwords.generators.external-secrets.io spec: diff --git a/deploy/crds/bundle.yaml b/deploy/crds/bundle.yaml index 7933ba26fad..9fb6bfd22f7 100644 --- a/deploy/crds/bundle.yaml +++ b/deploy/crds/bundle.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: clusterexternalsecrets.external-secrets.io spec: @@ -456,7 +456,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: clustersecretstores.external-secrets.io spec: @@ -3005,7 +3005,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: externalsecrets.external-secrets.io spec: @@ -3623,7 +3623,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: pushsecrets.external-secrets.io spec: @@ -3837,7 +3837,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: secretstores.external-secrets.io spec: @@ -6386,7 +6386,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: acraccesstokens.generators.external-secrets.io spec: @@ -6527,7 +6527,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: ecrauthorizationtokens.generators.external-secrets.io spec: @@ -6655,7 +6655,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: fakes.generators.external-secrets.io spec: @@ -6713,7 +6713,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: gcraccesstokens.generators.external-secrets.io spec: @@ -6821,7 +6821,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 creationTimestamp: null name: passwords.generators.external-secrets.io spec: diff --git a/e2e/go.mod b/e2e/go.mod index 80171334f10..a43130153d5 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -39,37 +39,37 @@ replace ( require ( cloud.google.com/go/secretmanager v1.10.0 - github.com/Azure/azure-sdk-for-go v67.3.0+incompatible + github.com/Azure/azure-sdk-for-go v68.0.0+incompatible github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 github.com/akeylesslabs/akeyless-go/v2 v2.20.3 - github.com/aliyun/alibaba-cloud-sdk-go v1.62.146 + github.com/aliyun/alibaba-cloud-sdk-go v1.62.155 github.com/argoproj/argo-cd/v2 v2.4.8 - github.com/aws/aws-sdk-go v1.44.192 + github.com/aws/aws-sdk-go v1.44.195 github.com/external-secrets/external-secrets v0.0.0 github.com/fluxcd/helm-controller/api v0.22.2 github.com/fluxcd/pkg/apis/meta v0.14.2 github.com/fluxcd/source-controller/api v0.25.11 github.com/golang-jwt/jwt/v4 v4.4.3 - github.com/hashicorp/vault/api v1.8.2 + github.com/hashicorp/vault/api v1.8.3 github.com/onsi/ginkgo/v2 v2.8.0 - github.com/onsi/gomega v1.25.0 + github.com/onsi/gomega v1.26.0 github.com/oracle/oci-go-sdk/v56 v56.1.0 - github.com/xanzy/go-gitlab v0.78.0 - golang.org/x/oauth2 v0.3.0 - google.golang.org/api v0.103.0 - k8s.io/api v0.26.0 - k8s.io/apiextensions-apiserver v0.26.0 - k8s.io/apimachinery v0.26.0 + github.com/xanzy/go-gitlab v0.79.1 + golang.org/x/oauth2 v0.4.0 + google.golang.org/api v0.109.0 + k8s.io/api v0.26.1 + k8s.io/apiextensions-apiserver v0.26.1 + k8s.io/apimachinery v0.26.1 k8s.io/client-go v1.5.2 - k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 - sigs.k8s.io/controller-runtime v0.14.1 + k8s.io/utils v0.0.0-20230202215443-34013725500c + sigs.k8s.io/controller-runtime v0.14.4 software.sslmate.com/src/go-pkcs12 v0.2.0 ) require ( - cloud.google.com/go/compute v1.13.0 // indirect - cloud.google.com/go/compute/metadata v0.2.1 // indirect + cloud.google.com/go/compute v1.18.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v0.10.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect @@ -88,24 +88,24 @@ require ( github.com/acomagu/bufpipe v1.0.3 // indirect github.com/argoproj/gitops-engine v0.7.3 // indirect github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0 // indirect - github.com/armon/go-metrics v0.4.0 // indirect + github.com/armon/go-metrics v0.4.1 // indirect github.com/armon/go-radix v1.0.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bombsimon/logrusr/v2 v2.0.1 // indirect github.com/bradleyfalzon/ghinstallation/v2 v2.0.4 // indirect github.com/cenkalti/backoff/v3 v3.2.2 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dimchansky/utfbom v1.1.1 // indirect github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/emicklei/go-restful/v3 v3.10.0 // indirect + github.com/emicklei/go-restful/v3 v3.10.1 // indirect github.com/emirpasic/gods v1.12.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect github.com/fatih/camelcase v1.0.0 // indirect - github.com/fatih/color v1.13.0 // indirect + github.com/fatih/color v1.14.1 // indirect github.com/fluxcd/pkg/apis/acl v0.0.3 // indirect github.com/fluxcd/pkg/apis/kustomize v0.4.1 // indirect github.com/frankban/quicktest v1.14.3 // indirect @@ -117,8 +117,8 @@ require ( github.com/go-git/go-billy/v5 v5.3.1 // indirect github.com/go-git/go-git/v5 v5.4.2 // indirect github.com/go-logr/logr v1.2.3 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.3 // indirect github.com/go-redis/cache/v8 v8.4.2 // indirect github.com/go-redis/redis/v8 v8.11.3 // indirect @@ -134,19 +134,19 @@ require ( github.com/google/go-github/v41 v41.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20220829040838-70bd9ae97f40 // indirect + github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.1 // indirect github.com/googleapis/gax-go/v2 v2.7.0 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-hclog v1.3.0 // indirect + github.com/hashicorp/go-hclog v1.4.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.4.5 // indirect - github.com/hashicorp/go-retryablehttp v0.7.1 // indirect + github.com/hashicorp/go-plugin v1.4.8 // indirect + github.com/hashicorp/go-retryablehttp v0.7.2 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 // indirect github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 // indirect @@ -155,11 +155,11 @@ require ( github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect - github.com/hashicorp/hcl v1.0.1-vault-3 // indirect - github.com/hashicorp/vault/sdk v0.6.0 // indirect + github.com/hashicorp/hcl v1.0.1-vault-5 // indirect + github.com/hashicorp/vault/sdk v0.7.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/imdario/mergo v0.3.13 // indirect - github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect @@ -171,8 +171,8 @@ require ( github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect @@ -195,8 +195,8 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.37.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect + github.com/prometheus/common v0.39.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect github.com/robfig/cron v1.2.0 // indirect github.com/russross/blackfriday v1.5.2 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect @@ -208,7 +208,7 @@ require ( github.com/stretchr/testify v1.8.1 // indirect github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.0 // indirect + github.com/tidwall/pretty v1.2.1 // indirect github.com/vmihailenco/go-tinylfu v0.2.1 // indirect github.com/vmihailenco/msgpack/v5 v5.3.4 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect @@ -218,17 +218,17 @@ require ( go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect go.uber.org/atomic v1.10.0 // indirect golang.org/x/crypto v0.5.0 // indirect - golang.org/x/exp v0.0.0-20221012211006-4de253d81b95 // indirect + golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect golang.org/x/net v0.5.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.4.0 // indirect + golang.org/x/sys v0.5.0 // indirect golang.org/x/term v0.4.0 // indirect golang.org/x/text v0.6.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.5.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 // indirect + google.golang.org/genproto v0.0.0-20230202175211-008b39050e57 // indirect google.golang.org/grpc v1.52.3 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect @@ -240,14 +240,14 @@ require ( grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 // indirect k8s.io/apiserver v0.24.2 // indirect k8s.io/cli-runtime v0.24.2 // indirect - k8s.io/component-base v0.26.0 // indirect + k8s.io/component-base v0.26.1 // indirect k8s.io/component-helpers v0.24.2 // indirect - k8s.io/klog/v2 v2.80.1 // indirect + k8s.io/klog/v2 v2.90.0 // indirect k8s.io/kube-aggregator v0.24.2 // indirect - k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect + k8s.io/kube-openapi v0.0.0-20230202010329-39b3636cbaa3 // indirect k8s.io/kubectl v0.24.2 // indirect k8s.io/kubernetes v1.24.2 // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/kustomize/api v0.11.4 // indirect sigs.k8s.io/kustomize/kyaml v0.13.6 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect diff --git a/e2e/go.sum b/e2e/go.sum index e98ecdd11bf..a751fb3644b 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -27,10 +27,10 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.13.0 h1:AYrLkB8NPdDRslNp4Jxmzrhdr03fUAIDbiGFjLWowoU= -cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= -cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= @@ -51,8 +51,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-sdk-for-go v55.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v67.3.0+incompatible h1:QEvenaO+Y9ShPeCWsSAtolzVUcb0T0tPeek5TDsovuM= -github.com/Azure/azure-sdk-for-go v67.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= @@ -126,8 +126,8 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI= github.com/alicebob/miniredis/v2 v2.14.2 h1:VeoqKUAsJfT2af61nDE7qhBzqn3J6xjnt9MFAbdrEtg= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.146 h1:zAH0YjWzonbKHvNkfbxqTmX51uHbkQYu+jJah2IAiCA= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.146/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.155 h1:qFWDgp7fsmkpfJZfpaTwppg9gptneYURTczlOP5lHI8= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.155/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -143,8 +143,8 @@ github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0/go.mod h1:ra+bQPmb github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.4.0 h1:yCQqn7dwca4ITXb+CbubHmedzaQYHhNhrEXLYUeEe8Q= -github.com/armon/go-metrics v0.4.0/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -159,8 +159,8 @@ github.com/aws/aws-sdk-go v1.33.16/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZve github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= github.com/aws/aws-sdk-go v1.38.49/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.44.192 h1:KL54vCxRd5v5XBGjnF3FelzXXwl+aWHDmDTihFmRNgM= -github.com/aws/aws-sdk-go v1.44.192/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.195 h1:d5xFL0N83Fpsq2LFiHgtBUHknCRUPGHdOlCWt/jtOJs= +github.com/aws/aws-sdk-go v1.44.195/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -188,8 +188,9 @@ github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6 github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 h1:HD4PLRzjuCVW79mQ0/pdsalOLHJ+FaEoqJLxfltpb2U= github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= @@ -276,8 +277,8 @@ github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7fo github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful/v3 v3.10.0 h1:X4gma4HM7hFm6WMeAsTfqA0GOfdNoCzBIkHGoRLGXuM= -github.com/emicklei/go-restful/v3 v3.10.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= +github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= @@ -300,8 +301,9 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZM github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= @@ -354,11 +356,9 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= @@ -369,12 +369,13 @@ github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= @@ -498,8 +499,8 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20220829040838-70bd9ae97f40 h1:ykKxL12NZd3JmWZnyqarJGsF73M9Xhtrik/FEtEeFRE= -github.com/google/pprof v0.0.0-20220829040838-70bd9ae97f40/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -508,8 +509,8 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.2.1 h1:RY7tHKZcRlk788d5WSo/e83gOyyy742E8GSs771ySpg= +github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= @@ -549,8 +550,8 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v1.3.0 h1:G0ACM8Z2WilWgPv3Vdzwm3V0BQu/kSmrkVtpe1fy9do= -github.com/hashicorp/go-hclog v1.3.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.4.0 h1:ctuWFGrhFha8BnnzxqeRGidlEcQkDyL5u8J8t5eA11I= +github.com/hashicorp/go-hclog v1.4.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -558,11 +559,11 @@ github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iP github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.4.5 h1:oTE/oQR4eghggRg8VY7PAz3dr++VwDNBGCcOfIvHpBo= -github.com/hashicorp/go-plugin v1.4.5/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= +github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM= +github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ= -github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0= +github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= @@ -590,16 +591,16 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/hcl v1.0.1-vault-3 h1:V95v5KSTu6DB5huDSKiq4uAfILEuNigK/+qPET6H/Mg= -github.com/hashicorp/hcl v1.0.1-vault-3/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= +github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= +github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/vault/api v1.8.2 h1:C7OL9YtOtwQbTKI9ogB0A1wffRbCN+rH/LLCHO3d8HM= -github.com/hashicorp/vault/api v1.8.2/go.mod h1:ML8aYzBIhY5m1MD1B2Q0JV89cC85YVH4t5kBaZiyVaE= -github.com/hashicorp/vault/sdk v0.6.0 h1:6Z+In5DXHiUfZvIZdMx7e2loL1PPyDjA4bVh9ZTIAhs= -github.com/hashicorp/vault/sdk v0.6.0/go.mod h1:+DRpzoXIdMvKc88R4qxr+edwy/RvH5QK8itmxLiDHLc= +github.com/hashicorp/vault/api v1.8.3 h1:cHQOLcMhBR+aVI0HzhPxO62w2+gJhIrKguQNONPzu6o= +github.com/hashicorp/vault/api v1.8.3/go.mod h1:4g/9lj9lmuJQMtT6CmVMHC5FW1yENaVv+Nv4ZfG8fAg= +github.com/hashicorp/vault/sdk v0.7.0 h1:2pQRO40R1etpKkia5fb4kjrdYMx3BHklPxl1pxpxDHg= +github.com/hashicorp/vault/sdk v0.7.0/go.mod h1:KyfArJkhooyba7gYCKSq8v66QdqJmnbAxtV/OX1+JTs= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/heketi/heketi v10.3.0+incompatible/go.mod h1:bB9ly3RchcQqsQ9CpyaQwvva7RS5ytVoSoholZQON6o= @@ -613,8 +614,9 @@ github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/ishidawataru/sctp v0.0.0-20190723014705-7c296d48a2b5/go.mod h1:DM4VvS+hD/kDi1U1QsX2fnZowwBhqD0Dk3bRPKF/Oc8= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= @@ -704,14 +706,15 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM= -github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989/go.mod h1:2eu9pRWp8mo84xCg6KswZ+USQHjwgRhNp06sozOdsTY= github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw= @@ -797,8 +800,8 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= -github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y= -github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= +github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= +github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -875,8 +878,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= +github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -886,8 +889,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/quobyte/api v0.1.8/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -985,8 +988,9 @@ github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -1010,8 +1014,8 @@ github.com/vmihailenco/msgpack/v5 v5.3.4/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= -github.com/xanzy/go-gitlab v0.78.0 h1:8jUHfQVAprG04Av5g0PxVd3CNsZ5hCbojIax7Hba1mE= -github.com/xanzy/go-gitlab v0.78.0/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M= +github.com/xanzy/go-gitlab v0.79.1 h1:ZmEei8RZYlqk4D7nYrWWZqywmKBOd7vmPMlJbueZXUU= +github.com/xanzy/go-gitlab v0.79.1/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -1082,7 +1086,7 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/ go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= @@ -1130,8 +1134,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20210220032938-85be41e4509f/go.mod h1:I6l2HNBLBZEcrOoCpyKLdY2lHoRZ8lI4x60KMCQDft4= golang.org/x/exp v0.0.0-20210901193431-a062eea981d2/go.mod h1:a3o/VtDNHN+dCVLEpzjjUHOzR+Ln3DHX056ZPzoZGGA= -golang.org/x/exp v0.0.0-20221012211006-4de253d81b95 h1:sBdrWpxhGDdTAYNqbgBLAR+ULAPPhfgncLr1X0lyWtg= -golang.org/x/exp v0.0.0-20221012211006-4de253d81b95/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= +golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1222,7 +1226,6 @@ golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= @@ -1243,9 +1246,8 @@ golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8= -golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= +golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1354,8 +1356,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1488,8 +1490,8 @@ google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.45.0/go.mod h1:ISLIJCedJolbZvDfAk+Ctuq5hf+aJ33WgtUsfyFoLXA= google.golang.org/api v0.46.0/go.mod h1:ceL4oozhkAiTID8XMmJBsIxID/9wMXJVVFXPg4ylg3I= -google.golang.org/api v0.103.0 h1:9yuVqlu2JCvcLg9p8S3fcFLZij8EPSyvODIY1rkMizQ= -google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +google.golang.org/api v0.109.0 h1:sW9hgHyX497PP5//NUM7nqfV8D0iDfBApqq7sOh1XR8= +google.golang.org/api v0.109.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1549,8 +1551,8 @@ google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 h1:p0kMzw6AG0JEzd7Z+kXqOiLhC6gjUQTbtS2zR0Q3DbI= -google.golang.org/genproto v0.0.0-20230131230820-1c016267d619/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230202175211-008b39050e57 h1:vArvWooPH749rNHpBGgVl+U9B9dATjiEhJzcWGlovNs= +google.golang.org/genproto v0.0.0-20230202175211-008b39050e57/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1685,15 +1687,15 @@ k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.5.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.90.0 h1:VkTxIV/FjRXn1fgNNcKGM8cfmL1Z33ZjXRTVxKCoF5M= +k8s.io/klog/v2 v2.90.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-aggregator v0.24.2 h1:vaKw45vFA5fIT0wdSehPIL7idjVxgLqz6iedOHedLG4= k8s.io/kube-aggregator v0.24.2/go.mod h1:Ju2jNDixn+vqeeKEBfjfpc204bO1pbdXX0N9knCxeMQ= k8s.io/kube-controller-manager v0.24.2/go.mod h1:KDE0yqiEvxYiO0WRpPA4rVx8AcK1vsWydUF37AJ9lTI= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= +k8s.io/kube-openapi v0.0.0-20230202010329-39b3636cbaa3 h1:vV3ZKAUX0nMjTflyfVea98dTfROpIxDaEsQws0FT2Ts= +k8s.io/kube-openapi v0.0.0-20230202010329-39b3636cbaa3/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= k8s.io/kube-proxy v0.24.2/go.mod h1:bozS2ufl/Ns6s40Ue34eV7rqyLVygi5usSmCgW7rFU8= k8s.io/kube-scheduler v0.24.2/go.mod h1:DRa+aeXKSYUUOHHIc/9EcaO9+FW5FydaOfPSvaSW5Ko= k8s.io/kubectl v0.24.2 h1:+RfQVhth8akUmIc2Ge8krMl/pt66V7210ka3RE/p0J4= @@ -1710,8 +1712,8 @@ k8s.io/system-validators v1.7.0/go.mod h1:gP1Ky+R9wtrSiFbrpEPwWMeYz9yqyy1S/KOh0V k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20230202215443-34013725500c h1:YVqDar2X7YiQa/DVAXFMDIfGF8uGrHQemlrwRU5NlVI= +k8s.io/utils v0.0.0-20230202215443-34013725500c/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= @@ -1725,8 +1727,8 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lR sigs.k8s.io/controller-runtime v0.11.2 h1:H5GTxQl0Mc9UjRJhORusqfJCIjBO8UtUxGggCwL1rLA= sigs.k8s.io/controller-runtime v0.11.2/go.mod h1:P6QCzrEjLaZGqHsfd+os7JQ+WFZhvB8MRFsn4dWF7O4= sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/kustomize/api v0.11.4 h1:/0Mr3kfBBNcNPOW5Qwk/3eb8zkswCwnqQxxKtmrTkRo= sigs.k8s.io/kustomize/api v0.11.4/go.mod h1:k+8RsqYbgpkIrJ4p9jcdPqe8DprLxFUUO0yNOq8C+xI= sigs.k8s.io/kustomize/cmd/config v0.10.6/go.mod h1:/S4A4nUANUa4bZJ/Edt7ZQTyKOY9WCER0uBS1SW2Rco= diff --git a/go.mod b/go.mod index 532f7ce6a53..bb9a9453363 100644 --- a/go.mod +++ b/go.mod @@ -35,11 +35,11 @@ replace ( require ( cloud.google.com/go/iam v0.10.0 cloud.google.com/go/secretmanager v1.10.0 - github.com/Azure/azure-sdk-for-go v67.3.0+incompatible + github.com/Azure/azure-sdk-for-go v68.0.0+incompatible github.com/Azure/go-autorest/autorest v0.11.28 github.com/Azure/go-autorest/autorest/adal v0.9.22 github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 - github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 + github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 github.com/IBM/go-sdk-core/v5 v5.12.0 github.com/IBM/secrets-manager-go-sdk v1.0.49 github.com/Masterminds/goutils v1.1.1 // indirect @@ -48,66 +48,66 @@ require ( github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 github.com/akeylesslabs/akeyless-go/v2 v2.20.3 - github.com/aliyun/alibaba-cloud-sdk-go v1.62.146 - github.com/aws/aws-sdk-go v1.44.192 + github.com/aliyun/alibaba-cloud-sdk-go v1.62.155 + github.com/aws/aws-sdk-go v1.44.195 github.com/go-logr/logr v1.2.3 github.com/go-test/deep v1.0.4 // indirect github.com/google/go-cmp v0.5.9 github.com/google/uuid v1.3.0 github.com/googleapis/gax-go/v2 v2.7.0 - github.com/hashicorp/vault/api v1.8.2 + github.com/hashicorp/vault/api v1.8.3 github.com/hashicorp/vault/api/auth/approle v0.3.0 github.com/hashicorp/vault/api/auth/kubernetes v0.3.0 github.com/hashicorp/vault/api/auth/ldap v0.3.0 - github.com/huandu/xstrings v1.3.3 // indirect + github.com/huandu/xstrings v1.4.0 // indirect github.com/lestrrat-go/jwx v1.2.25 github.com/onsi/ginkgo/v2 v2.8.0 - github.com/onsi/gomega v1.25.0 + github.com/onsi/gomega v1.26.0 github.com/oracle/oci-go-sdk/v56 v56.1.0 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 github.com/spf13/cobra v1.6.1 github.com/stretchr/testify v1.8.1 github.com/tidwall/gjson v1.14.4 - github.com/xanzy/go-gitlab v0.78.0 - github.com/yandex-cloud/go-genproto v0.0.0-20220902133259-5be489ec3a5d - github.com/yandex-cloud/go-sdk v0.0.0-20220902133848-327f1859d27a + github.com/xanzy/go-gitlab v0.79.1 + github.com/yandex-cloud/go-genproto v0.0.0-20230206132150-6ca32cf303b0 + github.com/yandex-cloud/go-sdk v0.0.0-20230206132606-87dc0cfe84bf github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a go.uber.org/zap v1.24.0 golang.org/x/crypto v0.5.0 - golang.org/x/oauth2 v0.3.0 - google.golang.org/api v0.103.0 - google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 // indirect + golang.org/x/oauth2 v0.4.0 + google.golang.org/api v0.109.0 + google.golang.org/genproto v0.0.0-20230202175211-008b39050e57 // indirect google.golang.org/grpc v1.52.3 gopkg.in/yaml.v3 v3.0.1 grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 - k8s.io/api v0.26.0 - k8s.io/apiextensions-apiserver v0.26.0 - k8s.io/apimachinery v0.26.0 + k8s.io/api v0.26.1 + k8s.io/apiextensions-apiserver v0.26.1 + k8s.io/apimachinery v0.26.1 k8s.io/client-go v1.5.2 - k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 - sigs.k8s.io/controller-runtime v0.14.1 - sigs.k8s.io/controller-tools v0.11.1 + k8s.io/utils v0.0.0-20230202215443-34013725500c + sigs.k8s.io/controller-runtime v0.14.4 + sigs.k8s.io/controller-tools v0.11.3 ) require github.com/1Password/connect-sdk-go v1.5.0 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 github.com/hashicorp/golang-lru v0.5.4 github.com/keeper-security/secrets-manager-go/core v1.4.0 - github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0 + github.com/maxbrunsfeld/counterfeiter/v6 v6.6.1 github.com/sethvargo/go-password v0.2.0 github.com/spf13/pflag v1.0.5 sigs.k8s.io/yaml v1.3.0 ) -require cloud.google.com/go/compute/metadata v0.2.1 // indirect +require cloud.google.com/go/compute/metadata v0.2.3 // indirect require ( - cloud.google.com/go/compute v1.13.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1 // indirect + cloud.google.com/go/compute v1.18.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect @@ -116,33 +116,33 @@ require ( github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/Masterminds/semver/v3 v3.2.0 // indirect - github.com/PaesslerAG/gval v1.2.0 // indirect - github.com/armon/go-metrics v0.4.0 // indirect + github.com/PaesslerAG/gval v1.2.2 // indirect + github.com/armon/go-metrics v0.4.1 // indirect github.com/armon/go-radix v1.0.0 // indirect github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v3 v3.2.2 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect github.com/dimchansky/utfbom v1.1.1 // indirect - github.com/emicklei/go-restful/v3 v3.10.0 // indirect + github.com/emicklei/go-restful/v3 v3.10.1 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect - github.com/fatih/color v1.13.0 // indirect + github.com/fatih/color v1.14.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-logr/zapr v1.2.3 // indirect github.com/go-openapi/errors v0.20.3 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/strfmt v0.21.3 // indirect github.com/go-openapi/swag v0.22.3 // indirect - github.com/go-playground/locales v0.14.0 // indirect - github.com/go-playground/universal-translator v0.18.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect - github.com/gobuffalo/flect v0.3.0 // indirect - github.com/goccy/go-json v0.9.11 // indirect + github.com/gobuffalo/flect v1.0.0 // indirect + github.com/goccy/go-json v0.10.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.4.3 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -151,15 +151,15 @@ require ( github.com/google/gnostic v0.6.9 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20220829040838-70bd9ae97f40 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect + github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-hclog v1.3.0 // indirect + github.com/hashicorp/go-hclog v1.4.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.4.5 // indirect - github.com/hashicorp/go-retryablehttp v0.7.1 // indirect + github.com/hashicorp/go-plugin v1.4.8 // indirect + github.com/hashicorp/go-retryablehttp v0.7.2 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 // indirect github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 // indirect @@ -167,11 +167,11 @@ require ( github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/hcl v1.0.1-vault-3 // indirect - github.com/hashicorp/vault/sdk v0.6.0 // indirect + github.com/hashicorp/hcl v1.0.1-vault-5 // indirect + github.com/hashicorp/vault/sdk v0.7.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/imdario/mergo v0.3.13 // indirect - github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -181,11 +181,11 @@ require ( github.com/lestrrat-go/blackmagic v1.0.1 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/iter v1.0.2 // indirect - github.com/lestrrat-go/option v1.0.0 // indirect + github.com/lestrrat-go/option v1.0.1 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect @@ -201,25 +201,25 @@ require ( github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/common v0.37.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect + github.com/prometheus/common v0.39.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/sony/gobreaker v0.5.0 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/tidwall/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.0 // indirect + github.com/tidwall/pretty v1.2.1 // indirect github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect github.com/uber/jaeger-lib v2.4.1+incompatible // indirect - go.mongodb.org/mongo-driver v1.10.1 // indirect + go.mongodb.org/mongo-driver v1.11.1 // indirect go.opencensus.io v0.24.0 // indirect go.uber.org/atomic v1.10.0 // indirect - go.uber.org/multierr v1.8.0 // indirect - golang.org/x/exp v0.0.0-20221012211006-4de253d81b95 + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/exp v0.0.0-20230206171751-46f607a40771 golang.org/x/mod v0.7.0 // indirect golang.org/x/net v0.5.0 // indirect - golang.org/x/sys v0.4.0 // indirect + golang.org/x/sys v0.5.0 // indirect golang.org/x/term v0.4.0 // indirect golang.org/x/text v0.6.0 // indirect golang.org/x/time v0.3.0 // indirect @@ -232,11 +232,11 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/component-base v0.26.0 // indirect - k8s.io/gengo v0.0.0-20220902162205-c0856e24416d // indirect + k8s.io/component-base v0.26.1 // indirect + k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9 // indirect k8s.io/klog v1.0.0 // indirect - k8s.io/klog/v2 v2.80.1 // indirect - k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + k8s.io/klog/v2 v2.90.0 // indirect + k8s.io/kube-openapi v0.0.0-20230202010329-39b3636cbaa3 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/go.sum b/go.sum index fdc9af36a5a..39852684ca6 100644 --- a/go.sum +++ b/go.sum @@ -25,10 +25,10 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.13.0 h1:AYrLkB8NPdDRslNp4Jxmzrhdr03fUAIDbiGFjLWowoU= -cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= -cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/iam v0.10.0 h1:fpP/gByFs6US1ma53v7VxhvbJpO2Aapng6wabJ99MuI= @@ -48,14 +48,14 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/1Password/connect-sdk-go v1.5.0 h1:F0WJcLSzGg3iXEDY49/ULdszYKsQLGTzn+2cyYXqiyk= github.com/1Password/connect-sdk-go v1.5.0/go.mod h1:TdynFeyvaRoackENbJ8RfJokH+WAowAu1MLmUbdMq6s= -github.com/Azure/azure-sdk-for-go v67.3.0+incompatible h1:QEvenaO+Y9ShPeCWsSAtolzVUcb0T0tPeek5TDsovuM= -github.com/Azure/azure-sdk-for-go v67.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1 h1:Oj853U9kG+RLTCQXpjvOnrv0WaZHxgmZz1TlLywgOPY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 h1:gVXuXcWd1i4C2Ruxe321aU+IKGaStvGB/S90PUPB/W8= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 h1:+5VZ72z0Qan5Bog5C+ZkgSqUbeVUd9wgtHOrIKuc5b8= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= @@ -82,8 +82,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM= -github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU= +github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg= +github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= @@ -101,8 +101,8 @@ github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I= -github.com/PaesslerAG/gval v1.2.0 h1:DA7PsxmtzlUU4bYxV35MKp9KDDVWcrJJRhlaCohMhsM= -github.com/PaesslerAG/gval v1.2.0/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbVR+C6xac= +github.com/PaesslerAG/gval v1.2.2 h1:Y7iBzhgE09IGTt5QgGQ2IdaYYYOU134YGHBThD+wm9E= +github.com/PaesslerAG/gval v1.2.2/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbVR+C6xac= github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8= github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk= github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY= @@ -117,13 +117,12 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.146 h1:zAH0YjWzonbKHvNkfbxqTmX51uHbkQYu+jJah2IAiCA= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.146/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.155 h1:qFWDgp7fsmkpfJZfpaTwppg9gptneYURTczlOP5lHI8= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.155/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= -github.com/armon/go-metrics v0.4.0 h1:yCQqn7dwca4ITXb+CbubHmedzaQYHhNhrEXLYUeEe8Q= -github.com/armon/go-metrics v0.4.0/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -131,8 +130,8 @@ github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:W github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.44.192 h1:KL54vCxRd5v5XBGjnF3FelzXXwl+aWHDmDTihFmRNgM= -github.com/aws/aws-sdk-go v1.44.192/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.195 h1:d5xFL0N83Fpsq2LFiHgtBUHknCRUPGHdOlCWt/jtOJs= +github.com/aws/aws-sdk-go v1.44.195/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -148,8 +147,8 @@ github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4r github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -174,8 +173,8 @@ github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/emicklei/go-restful/v3 v3.10.0 h1:X4gma4HM7hFm6WMeAsTfqA0GOfdNoCzBIkHGoRLGXuM= -github.com/emicklei/go-restful/v3 v3.10.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= +github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -192,8 +191,9 @@ github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2Vvl github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= @@ -213,13 +213,9 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -231,30 +227,30 @@ github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= github.com/go-openapi/errors v0.20.3 h1:rz6kiC84sqNQoqrtulzaL/VERgkoCyB6WdEkc2ujzUc= github.com/go-openapi/errors v0.20.3/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/strfmt v0.21.3 h1:xwhj5X6CjXEZZHMWy1zKJxvW9AfHC9pkyUjLvHtKG7o= github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= -github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/gobuffalo/flect v0.3.0 h1:erfPWM+K1rFNIQeRPdeEXxo8yFr/PO17lhRnS8FUrtk= -github.com/gobuffalo/flect v0.3.0/go.mod h1:5pf3aGnsvqvCj50AVni7mJJF8ICxGZ8HomberC3pXLE= +github.com/gobuffalo/flect v1.0.0 h1:eBFmskjXZgAOagiTXJH25Nt5sdFwNRcb8DKZsIsAUQI= +github.com/gobuffalo/flect v1.0.0/go.mod h1:l9V6xSb4BlXwsxEMj3FVEub2nkdQjWhPvD8XTTlHPQc= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= -github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= +github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -338,15 +334,15 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20220829040838-70bd9ae97f40 h1:ykKxL12NZd3JmWZnyqarJGsF73M9Xhtrik/FEtEeFRE= -github.com/google/pprof v0.0.0-20220829040838-70bd9ae97f40/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.2.1 h1:RY7tHKZcRlk788d5WSo/e83gOyyy742E8GSs771ySpg= +github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= @@ -362,8 +358,8 @@ github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/S github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v1.3.0 h1:G0ACM8Z2WilWgPv3Vdzwm3V0BQu/kSmrkVtpe1fy9do= -github.com/hashicorp/go-hclog v1.3.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.4.0 h1:ctuWFGrhFha8BnnzxqeRGidlEcQkDyL5u8J8t5eA11I= +github.com/hashicorp/go-hclog v1.4.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -372,12 +368,13 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= -github.com/hashicorp/go-plugin v1.4.5 h1:oTE/oQR4eghggRg8VY7PAz3dr++VwDNBGCcOfIvHpBo= -github.com/hashicorp/go-plugin v1.4.5/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= +github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM= +github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ= github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0= +github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-secure-stdlib/base62 v0.1.1/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw= @@ -407,32 +404,35 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/hcl v1.0.1-vault-3 h1:V95v5KSTu6DB5huDSKiq4uAfILEuNigK/+qPET6H/Mg= -github.com/hashicorp/hcl v1.0.1-vault-3/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= +github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= +github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= github.com/hashicorp/vault/api v1.8.0/go.mod h1:uJrw6D3y9Rv7hhmS17JQC50jbPDAZdjZoTtrCCxxs7E= -github.com/hashicorp/vault/api v1.8.2 h1:C7OL9YtOtwQbTKI9ogB0A1wffRbCN+rH/LLCHO3d8HM= -github.com/hashicorp/vault/api v1.8.2/go.mod h1:ML8aYzBIhY5m1MD1B2Q0JV89cC85YVH4t5kBaZiyVaE= +github.com/hashicorp/vault/api v1.8.3 h1:cHQOLcMhBR+aVI0HzhPxO62w2+gJhIrKguQNONPzu6o= +github.com/hashicorp/vault/api v1.8.3/go.mod h1:4g/9lj9lmuJQMtT6CmVMHC5FW1yENaVv+Nv4ZfG8fAg= github.com/hashicorp/vault/api/auth/approle v0.3.0 h1:Ib0oCNXsCq/QZhPYtXPzJEbGS5WR/KoZf8c84QoFdkU= github.com/hashicorp/vault/api/auth/approle v0.3.0/go.mod h1:hm51TbjzUkPO0Y17wkrpwOpvyyMRpXJNueTHiG04t3k= github.com/hashicorp/vault/api/auth/kubernetes v0.3.0 h1:HkaCmTKzcgLa2tjdiAid1rbmyQNmQGHfnmvIIM2WorY= github.com/hashicorp/vault/api/auth/kubernetes v0.3.0/go.mod h1:l1B4MGtLc+P37MabBQiIhP3qd9agj0vqhETmaQjjC/Y= github.com/hashicorp/vault/api/auth/ldap v0.3.0 h1:G2Hk03lwqaeHcjBmYtR+aHDzttw5qE3r3oQr+F4O7Ro= github.com/hashicorp/vault/api/auth/ldap v0.3.0/go.mod h1:WhIWEHgzyr99FQbna94Y0twKmz3sbtPGbVtIy40Oyik= -github.com/hashicorp/vault/sdk v0.6.0 h1:6Z+In5DXHiUfZvIZdMx7e2loL1PPyDjA4bVh9ZTIAhs= github.com/hashicorp/vault/sdk v0.6.0/go.mod h1:+DRpzoXIdMvKc88R4qxr+edwy/RvH5QK8itmxLiDHLc= +github.com/hashicorp/vault/sdk v0.7.0 h1:2pQRO40R1etpKkia5fb4kjrdYMx3BHklPxl1pxpxDHg= +github.com/hashicorp/vault/sdk v0.7.0/go.mod h1:KyfArJkhooyba7gYCKSq8v66QdqJmnbAxtV/OX1+JTs= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= -github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= @@ -443,18 +443,14 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/keeper-security/secrets-manager-go/core v1.4.0 h1:6x65lMBPwHNirQRXwGByCHrzJx7LDWt06uBUKCLs92w= github.com/keeper-security/secrets-manager-go/core v1.4.0/go.mod h1:dtlaeeds9+SZsbDAZnQRsDSqEAK9a62SYtqhNql+VgQ= @@ -462,7 +458,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -488,10 +483,9 @@ github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzlt github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4= github.com/lestrrat-go/jwx v1.2.25 h1:tAx93jN2SdPvFn08fHNAhqFJazn5mBBOB8Zli0g0otA= github.com/lestrrat-go/jwx v1.2.25/go.mod h1:zoNuZymNl5lgdcu6P7K6ie2QRll5HVfF4xwxBBK1NxY= -github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4= github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= +github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -506,13 +500,14 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM= -github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0 h1:rBhB9Rls+yb8kA4x5a/cWxOufWfXt24E+kq4YlbGj3g= -github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0/go.mod h1:fJ0UAZc1fx3xZhU4eSHQDJ1ApFmTVhp5VTpV9tm2ogg= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/maxbrunsfeld/counterfeiter/v6 v6.6.1 h1:9XE5ykDiC8eNSqIPkxx0EsV3kMX1oe4kQWRZjIgytUA= +github.com/maxbrunsfeld/counterfeiter/v6 v6.6.1/go.mod h1:qbKwBR+qQODzH2WD/s53mdgp/xVcXMlJb59GRFOp6Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= @@ -542,7 +537,6 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= @@ -564,8 +558,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.0/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y= -github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= +github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= +github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= @@ -588,9 +582,6 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -601,19 +592,13 @@ github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvq github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= +github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= @@ -632,7 +617,6 @@ github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sony/gobreaker v0.4.2-0.20210216022020-dd874f9dd33b/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg= github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= @@ -666,25 +650,26 @@ github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vl github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/xanzy/go-gitlab v0.78.0 h1:8jUHfQVAprG04Av5g0PxVd3CNsZ5hCbojIax7Hba1mE= -github.com/xanzy/go-gitlab v0.78.0/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M= +github.com/xanzy/go-gitlab v0.79.1 h1:ZmEei8RZYlqk4D7nYrWWZqywmKBOd7vmPMlJbueZXUU= +github.com/xanzy/go-gitlab v0.79.1/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/yandex-cloud/go-genproto v0.0.0-20220902133259-5be489ec3a5d h1:9SncSKVHgZwOE4tqaPL6M8z8W/d44vMLKOUjpDNwVhU= -github.com/yandex-cloud/go-genproto v0.0.0-20220902133259-5be489ec3a5d/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= -github.com/yandex-cloud/go-sdk v0.0.0-20220902133848-327f1859d27a h1:QYBJihRF0pfDasFnHZK5JmA/wwymleIxG+OTSkDtSR0= -github.com/yandex-cloud/go-sdk v0.0.0-20220902133848-327f1859d27a/go.mod h1:OQLAYnEbSr3ax1soqYhNwDpCBT+vf4GiwSYOPkeo4bE= +github.com/yandex-cloud/go-genproto v0.0.0-20230206132150-6ca32cf303b0 h1:Agj+9yFgZYa7ojWmcXNHy83WZ//Qz1RzSRZRaNmIi3Q= +github.com/yandex-cloud/go-genproto v0.0.0-20230206132150-6ca32cf303b0/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= +github.com/yandex-cloud/go-sdk v0.0.0-20230206132606-87dc0cfe84bf h1:jjy3J5XOv2LsD60IOJOYjhyWYaV2UNudbo5xDUucrjo= +github.com/yandex-cloud/go-sdk v0.0.0-20230206132606-87dc0cfe84bf/go.mod h1:ZXQgvDrguV3h/Ir0AqvC/ktopsKBiHORacW9lbi934k= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= @@ -694,8 +679,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= -go.mongodb.org/mongo-driver v1.10.1 h1:NujsPveKwHaWuKUer/ceo9DzEe7HIj1SlJ6uvXZG0S4= -go.mongodb.org/mongo-driver v1.10.1/go.mod h1:z4XpeoU6w+9Vht+jAFyLgVrD+jGSQQe0+CBWFHNiHt8= +go.mongodb.org/mongo-driver v1.11.1 h1:QP0znIRTuL0jf1oBQoAoM0C6ZJfBK4kx0Uumtv1A7w8= +go.mongodb.org/mongo-driver v1.11.1/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -713,8 +698,8 @@ go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0 go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= -go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= @@ -747,8 +732,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20221012211006-4de253d81b95 h1:sBdrWpxhGDdTAYNqbgBLAR+ULAPPhfgncLr1X0lyWtg= -golang.org/x/exp v0.0.0-20221012211006-4de253d81b95/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= +golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -816,12 +801,9 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= @@ -839,10 +821,8 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8= -golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= +golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -878,7 +858,6 @@ golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -892,8 +871,6 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -902,7 +879,6 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -911,13 +887,11 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -925,8 +899,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1039,8 +1013,8 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.45.0/go.mod h1:ISLIJCedJolbZvDfAk+Ctuq5hf+aJ33WgtUsfyFoLXA= -google.golang.org/api v0.103.0 h1:9yuVqlu2JCvcLg9p8S3fcFLZij8EPSyvODIY1rkMizQ= -google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +google.golang.org/api v0.109.0 h1:sW9hgHyX497PP5//NUM7nqfV8D0iDfBApqq7sOh1XR8= +google.golang.org/api v0.109.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1093,8 +1067,8 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 h1:p0kMzw6AG0JEzd7Z+kXqOiLhC6gjUQTbtS2zR0Q3DbI= -google.golang.org/genproto v0.0.0-20230131230820-1c016267d619/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230202175211-008b39050e57 h1:vArvWooPH749rNHpBGgVl+U9B9dATjiEhJzcWGlovNs= +google.golang.org/genproto v0.0.0-20230202175211-008b39050e57/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -1141,6 +1115,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= @@ -1193,28 +1168,28 @@ k8s.io/client-go v0.26.0/go.mod h1:I2Sh57A79EQsDmn7F7ASpmru1cceh3ocVT9KlX2jEZg= k8s.io/component-base v0.26.0 h1:0IkChOCohtDHttmKuz+EP3j3+qKmV55rM9gIFTXA7Vs= k8s.io/component-base v0.26.0/go.mod h1:lqHwlfV1/haa14F/Z5Zizk5QmzaVf23nQzCwVOQpfC8= k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20220902162205-c0856e24416d h1:U9tB195lKdzwqicbJvyJeOXV7Klv+wNAWENRnXEGi08= -k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9 h1:iu3o/SxaHVI7tKPtkGzD3M9IzrE21j+CUKH98NQJ8Ms= +k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/klog/v2 v2.90.0 h1:VkTxIV/FjRXn1fgNNcKGM8cfmL1Z33ZjXRTVxKCoF5M= +k8s.io/klog/v2 v2.90.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20230202010329-39b3636cbaa3 h1:vV3ZKAUX0nMjTflyfVea98dTfROpIxDaEsQws0FT2Ts= +k8s.io/kube-openapi v0.0.0-20230202010329-39b3636cbaa3/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= +k8s.io/utils v0.0.0-20230202215443-34013725500c h1:YVqDar2X7YiQa/DVAXFMDIfGF8uGrHQemlrwRU5NlVI= +k8s.io/utils v0.0.0-20230202215443-34013725500c/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/controller-runtime v0.14.1 h1:vThDes9pzg0Y+UbCPY3Wj34CGIYPgdmspPm2GIpxpzM= -sigs.k8s.io/controller-runtime v0.14.1/go.mod h1:GaRkrY8a7UZF0kqFFbUKG7n9ICiTY5T55P1RiE3UZlU= -sigs.k8s.io/controller-tools v0.11.1 h1:blfU7DbmXuACWHfpZR645KCq8cLOc6nfkipGSGnH+Wk= -sigs.k8s.io/controller-tools v0.11.1/go.mod h1:dm4bN3Yp1ZP+hbbeSLF8zOEHsI1/bf15u3JNcgRv2TM= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/controller-runtime v0.14.4 h1:Kd/Qgx5pd2XUL08eOV2vwIq3L9GhIbJ5Nxengbd4/0M= +sigs.k8s.io/controller-runtime v0.14.4/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= +sigs.k8s.io/controller-tools v0.11.3 h1:T1xzLkog9saiyQSLz1XOImu4OcbdXWytc5cmYsBeBiE= +sigs.k8s.io/controller-tools v0.11.3/go.mod h1:qcfX7jfcfYD/b7lAhvqAyTbt/px4GpvN88WKLFFv7p8= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= From fe3c78d2af1202331df6bfbc7237f5f310dd5c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20G=C3=B3mez?= <1637983+sebagomez@users.noreply.github.com> Date: Tue, 7 Feb 2023 11:35:25 -0300 Subject: [PATCH 18/62] Fixed broken link (#1992) --- docs/api/externalsecret.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/externalsecret.md b/docs/api/externalsecret.md index 7daaeb65ae6..e4d2c832503 100644 --- a/docs/api/externalsecret.md +++ b/docs/api/externalsecret.md @@ -27,7 +27,7 @@ kubectl annotate es my-es force-sync=$(date +%s) --overwrite ## Features -Individual features are described in the [Guides section](../guides/): +Individual features are described in the [Guides section](../guides/introduction.md): * [Find many secrets / Extract from structured data](../guides/getallsecrets.md) * [Templating](../guides/templating.md) From 1e041770459b7874c7f761c50e7fad12af3be021 Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Mon, 13 Feb 2023 10:33:38 +0100 Subject: [PATCH 19/62] fix: fix validation method in kubernetes provider (#2000) RBAC allows a user to define a wildcard `*` for a given field in the Resource Rule. Prefix/Suffix matching or globbing is not supported, just simple wildcards. For example the cluster-admin role has a `*` on all apiVersion/resource/verbs and hence validation would fail. Signed-off-by: Moritz Johner --- pkg/provider/kubernetes/validate.go | 4 +++- pkg/provider/kubernetes/validate_test.go | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/pkg/provider/kubernetes/validate.go b/pkg/provider/kubernetes/validate.go index 9c37bcfb39c..9d709555e44 100644 --- a/pkg/provider/kubernetes/validate.go +++ b/pkg/provider/kubernetes/validate.go @@ -83,7 +83,9 @@ func (c *Client) Validate() (esv1beta1.ValidationResult, error) { return esv1beta1.ValidationResultUnknown, fmt.Errorf("could not verify if client is valid: %w", err) } for _, rev := range authReview.Status.ResourceRules { - if contains("secrets", rev.Resources) && contains("get", rev.Verbs) { + if (contains("secrets", rev.Resources) || contains("*", rev.Resources)) && + (contains("get", rev.Verbs) || contains("*", rev.Verbs)) && + (len(rev.APIGroups) == 0 || (contains("", rev.APIGroups) || contains("*", rev.APIGroups))) { return esv1beta1.ValidationResultReady, nil } } diff --git a/pkg/provider/kubernetes/validate_test.go b/pkg/provider/kubernetes/validate_test.go index 007c67cd280..e55a7c5111a 100644 --- a/pkg/provider/kubernetes/validate_test.go +++ b/pkg/provider/kubernetes/validate_test.go @@ -273,6 +273,17 @@ func TestValidate(t *testing.T) { }, }, } + successWildcardReview := authv1.SelfSubjectRulesReview{ + Status: authv1.SubjectRulesReviewStatus{ + ResourceRules: []authv1.ResourceRule{ + { + Verbs: []string{"*"}, + Resources: []string{"*"}, + APIGroups: []string{"*"}, + }, + }, + }, + } type fields struct { Client KClient @@ -333,6 +344,16 @@ func TestValidate(t *testing.T) { want: esv1beta1.ValidationResultReady, wantErr: false, }, + { + name: "allowed results in no error", + fields: fields{ + Namespace: "default", + ReviewClient: fakeReviewClient{authReview: &successWildcardReview}, + store: &esv1beta1.KubernetesProvider{}, + }, + want: esv1beta1.ValidationResultReady, + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From 151d83e8072a2646716a48444b7509242e2d64f3 Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Tue, 14 Feb 2023 18:42:44 +0100 Subject: [PATCH 20/62] chore: bump dependencies (#2012) * chore: bump dependencies Signed-off-by: Moritz Johner * fix: disable flow logs in EKS testbed This causes issues in the way we set up the trust relationship between GHA and AWS; We see a HTTP 400 when tf tries to assume this role. Because we don't need this we can disable it. Signed-off-by: Moritz Johner --------- Signed-off-by: Moritz Johner --- e2e/go.mod | 57 +++---- e2e/go.sum | 135 +++++------------ go.mod | 67 ++++----- go.sum | 209 +++++++------------------- terraform/aws/modules/cluster/main.tf | 6 +- 5 files changed, 139 insertions(+), 335 deletions(-) diff --git a/e2e/go.mod b/e2e/go.mod index a43130153d5..0dd1d052e1c 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -43,26 +43,26 @@ require ( github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 github.com/akeylesslabs/akeyless-go/v2 v2.20.3 - github.com/aliyun/alibaba-cloud-sdk-go v1.62.155 + github.com/aliyun/alibaba-cloud-sdk-go v1.62.164 github.com/argoproj/argo-cd/v2 v2.4.8 - github.com/aws/aws-sdk-go v1.44.195 + github.com/aws/aws-sdk-go v1.44.200 github.com/external-secrets/external-secrets v0.0.0 github.com/fluxcd/helm-controller/api v0.22.2 github.com/fluxcd/pkg/apis/meta v0.14.2 github.com/fluxcd/source-controller/api v0.25.11 github.com/golang-jwt/jwt/v4 v4.4.3 - github.com/hashicorp/vault/api v1.8.3 - github.com/onsi/ginkgo/v2 v2.8.0 + github.com/hashicorp/vault/api v1.9.0 + github.com/onsi/ginkgo/v2 v2.8.1 github.com/onsi/gomega v1.26.0 github.com/oracle/oci-go-sdk/v56 v56.1.0 - github.com/xanzy/go-gitlab v0.79.1 - golang.org/x/oauth2 v0.4.0 + github.com/xanzy/go-gitlab v0.80.0 + golang.org/x/oauth2 v0.5.0 google.golang.org/api v0.109.0 k8s.io/api v0.26.1 k8s.io/apiextensions-apiserver v0.26.1 k8s.io/apimachinery v0.26.1 k8s.io/client-go v1.5.2 - k8s.io/utils v0.0.0-20230202215443-34013725500c + k8s.io/utils v0.0.0-20230209194617-a36077c30491 sigs.k8s.io/controller-runtime v0.14.4 software.sslmate.com/src/go-pkcs12 v0.2.0 ) @@ -88,8 +88,6 @@ require ( github.com/acomagu/bufpipe v1.0.3 // indirect github.com/argoproj/gitops-engine v0.7.3 // indirect github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0 // indirect - github.com/armon/go-metrics v0.4.1 // indirect - github.com/armon/go-radix v1.0.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bombsimon/logrusr/v2 v2.0.1 // indirect github.com/bradleyfalzon/ghinstallation/v2 v2.0.4 // indirect @@ -105,10 +103,8 @@ require ( github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect github.com/fatih/camelcase v1.0.0 // indirect - github.com/fatih/color v1.14.1 // indirect github.com/fluxcd/pkg/apis/acl v0.0.3 // indirect github.com/fluxcd/pkg/apis/kustomize v0.4.1 // indirect - github.com/frankban/quicktest v1.14.3 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fvbommel/sortorder v1.0.1 // indirect github.com/ghodss/yaml v1.0.0 // indirect @@ -127,7 +123,6 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.0.1 // indirect github.com/google/gnostic v0.6.9 // indirect github.com/google/go-cmp v0.5.9 // indirect @@ -137,27 +132,18 @@ require ( github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.1 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/googleapis/gax-go/v2 v2.7.0 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-hclog v1.4.0 // indirect - github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.4.8 // indirect github.com/hashicorp/go-retryablehttp v0.7.2 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 // indirect github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect - github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/hcl v1.0.1-vault-5 // indirect - github.com/hashicorp/vault/sdk v0.7.0 // indirect - github.com/hashicorp/yamux v0.1.1 // indirect github.com/imdario/mergo v0.3.13 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect @@ -168,29 +154,23 @@ require ( github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect github.com/klauspost/compress v1.13.6 // indirect + github.com/kr/pretty v0.3.0 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/oklog/run v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect - github.com/pierrec/lz4 v2.6.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect @@ -216,20 +196,19 @@ require ( github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect go.opencensus.io v0.24.0 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect - go.uber.org/atomic v1.10.0 // indirect - golang.org/x/crypto v0.5.0 // indirect - golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect - golang.org/x/net v0.5.0 // indirect + golang.org/x/crypto v0.6.0 // indirect + golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb // indirect + golang.org/x/net v0.6.0 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.4.0 // indirect - golang.org/x/text v0.6.0 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.5.0 // indirect + golang.org/x/tools v0.6.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230202175211-008b39050e57 // indirect - google.golang.org/grpc v1.52.3 // indirect + google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc // indirect + google.golang.org/grpc v1.53.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect @@ -244,7 +223,7 @@ require ( k8s.io/component-helpers v0.24.2 // indirect k8s.io/klog/v2 v2.90.0 // indirect k8s.io/kube-aggregator v0.24.2 // indirect - k8s.io/kube-openapi v0.0.0-20230202010329-39b3636cbaa3 // indirect + k8s.io/kube-openapi v0.0.0-20230210211930-4b0756abdef5 // indirect k8s.io/kubectl v0.24.2 // indirect k8s.io/kubernetes v1.24.2 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/e2e/go.sum b/e2e/go.sum index a751fb3644b..7e0ec8c1ea3 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -86,7 +86,6 @@ github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUM github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/GoogleCloudPlatform/k8s-cloud-provider v1.16.1-0.20210702024009-ea6160c1d0e3/go.mod h1:8XasY4ymP2V/tn2OOV9ZadmiTE1FIB/h3W+yNlPttKw= github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5hodBMJ5+l/7J4xAyMeuM2PNuepvHlGs8yilUCA= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= @@ -126,8 +125,8 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI= github.com/alicebob/miniredis/v2 v2.14.2 h1:VeoqKUAsJfT2af61nDE7qhBzqn3J6xjnt9MFAbdrEtg= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.155 h1:qFWDgp7fsmkpfJZfpaTwppg9gptneYURTczlOP5lHI8= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.155/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.164 h1:1CaNFKN3P02nI0bbSfp4aY/rwHbu2Aot4Aj3YoUtw+s= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.164/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -143,11 +142,7 @@ github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0/go.mod h1:ra+bQPmb github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= -github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= @@ -159,8 +154,8 @@ github.com/aws/aws-sdk-go v1.33.16/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZve github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= github.com/aws/aws-sdk-go v1.38.49/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.44.195 h1:d5xFL0N83Fpsq2LFiHgtBUHknCRUPGHdOlCWt/jtOJs= -github.com/aws/aws-sdk-go v1.44.195/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.200 h1:JcFf/BnOaMWe9ObjaklgbbF0bGXI4XbYJwYn2eFNVyQ= +github.com/aws/aws-sdk-go v1.44.200/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -200,8 +195,6 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1wt9Z3DP8O6W3rvwCt0REIlshg1InHImaLW0t3ObY0= @@ -301,10 +294,7 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZM github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= -github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/fluxcd/helm-controller/api v0.22.2 h1:nh0GZBsUE0gNzm4PmPa4aOoqYlbZbpGt2pcIL9S2184= @@ -324,8 +314,6 @@ github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoD github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= -github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= @@ -448,8 +436,6 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -474,7 +460,6 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v41 v41.0.0 h1:HseJrM2JFf2vfiZJ8anY2hqBjdfY1Vlj/K27ueww4gg= @@ -509,8 +494,8 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.1 h1:RY7tHKZcRlk788d5WSo/e83gOyyy742E8GSs771ySpg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= @@ -545,30 +530,21 @@ github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyN github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v1.4.0 h1:ctuWFGrhFha8BnnzxqeRGidlEcQkDyL5u8J8t5eA11I= -github.com/hashicorp/go-hclog v1.4.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= -github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM= -github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= -github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0= github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 h1:p4AKXPPS24tO8Wc8i1gLvSKdmkiSY5xuju57czJ/IJQ= -github.com/hashicorp/go-secure-stdlib/mlock v0.1.2/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 h1:UpiO20jno/eV1eVZcxqWnUohyKRe1g8FPV/xH1s/2qs= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= @@ -580,16 +556,10 @@ github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjG github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= -github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= @@ -597,12 +567,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/vault/api v1.8.3 h1:cHQOLcMhBR+aVI0HzhPxO62w2+gJhIrKguQNONPzu6o= -github.com/hashicorp/vault/api v1.8.3/go.mod h1:4g/9lj9lmuJQMtT6CmVMHC5FW1yENaVv+Nv4ZfG8fAg= -github.com/hashicorp/vault/sdk v0.7.0 h1:2pQRO40R1etpKkia5fb4kjrdYMx3BHklPxl1pxpxDHg= -github.com/hashicorp/vault/sdk v0.7.0/go.mod h1:KyfArJkhooyba7gYCKSq8v66QdqJmnbAxtV/OX1+JTs= -github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= -github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/hashicorp/vault/api v1.9.0 h1:ab7dI6W8DuCY7yCU8blo0UCYl2oHre/dloCmzMWg9w8= +github.com/hashicorp/vault/api v1.9.0/go.mod h1:lloELQP4EyhjnCQhF8agKvWIVTmxbpEJj70b98959sM= github.com/heketi/heketi v10.3.0+incompatible/go.mod h1:bB9ly3RchcQqsQ9CpyaQwvva7RS5ytVoSoholZQON6o= github.com/heketi/tests v0.0.0-20151005000721-f3775cbcefd6/go.mod h1:xGMAM8JLi7UkZt1i4FQeQy0R2T8GLUwQhOP5M1gBhy4= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -623,7 +589,6 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= @@ -640,7 +605,6 @@ github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -698,17 +662,10 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -722,14 +679,10 @@ github.com/minio/minio-go/v7 v7.0.2/go.mod h1:dJ80Mv2HeGkYLH1sqS/ksz07ON6csH3S6J github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= -github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= @@ -739,8 +692,6 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/ipvs v1.0.1/go.mod h1:2pngiyseZbIKXNv7hsKj3O9UEz30c53MT9005gt2hxQ= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= @@ -780,8 +731,6 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= -github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= @@ -793,8 +742,8 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI= -github.com/onsi/ginkgo/v2 v2.8.0/go.mod h1:6JsQiECmxCa3V5st74AL/AmsV482EDdVrGaVW6z3oYU= +github.com/onsi/ginkgo/v2 v2.8.1 h1:xFTEVwOFa1D/Ty24Ws1npBWkDYEV9BqZrsDxVrVkrrU= +github.com/onsi/ginkgo/v2 v2.8.1/go.mod h1:N1/NbDngAFcSLdyZ+/aYTYGSlq9qMCS/cNKGJjy+csc= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= @@ -826,8 +775,6 @@ github.com/oracle/oci-go-sdk/v56 v56.1.0 h1:HOr9P+MkwgrilEGTJCU7a6GMFrUG/RZAzvh/ github.com/oracle/oci-go-sdk/v56 v56.1.0/go.mod h1:kDJAL3HEAF+4oQR8GfaOkY6rz2kU3/kZ6vYJnJXSCkA= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= @@ -838,8 +785,6 @@ github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+v github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= -github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -855,7 +800,6 @@ github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= -github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= @@ -874,7 +818,6 @@ github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= @@ -901,8 +844,8 @@ github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzG github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.21.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM= github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= @@ -978,7 +921,6 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= @@ -994,7 +936,6 @@ github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhso github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= @@ -1014,8 +955,8 @@ github.com/vmihailenco/msgpack/v5 v5.3.4/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= -github.com/xanzy/go-gitlab v0.79.1 h1:ZmEei8RZYlqk4D7nYrWWZqywmKBOd7vmPMlJbueZXUU= -github.com/xanzy/go-gitlab v0.79.1/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M= +github.com/xanzy/go-gitlab v0.80.0 h1:2d6RwUrI3ZC2Xh9urnqiiHCLzWNndrGtje3yByZubdQ= +github.com/xanzy/go-gitlab v0.80.0/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -1079,7 +1020,6 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -1115,8 +1055,8 @@ golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1134,8 +1074,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20210220032938-85be41e4509f/go.mod h1:I6l2HNBLBZEcrOoCpyKLdY2lHoRZ8lI4x60KMCQDft4= golang.org/x/exp v0.0.0-20210901193431-a062eea981d2/go.mod h1:a3o/VtDNHN+dCVLEpzjjUHOzR+Ln3DHX056ZPzoZGGA= -golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= -golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w= +golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1228,8 +1168,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1246,8 +1186,8 @@ golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1296,7 +1236,6 @@ golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1340,20 +1279,16 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210608053332-aa57babbf139/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= @@ -1361,8 +1296,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1373,8 +1308,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1451,8 +1386,8 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4= -golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1551,8 +1486,8 @@ google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230202175211-008b39050e57 h1:vArvWooPH749rNHpBGgVl+U9B9dATjiEhJzcWGlovNs= -google.golang.org/genproto v0.0.0-20230202175211-008b39050e57/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc h1:ijGwO+0vL2hJt5gaygqP2j6PfflOBrRot0IczKbmtio= +google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1580,8 +1515,8 @@ google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ= -google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1694,8 +1629,8 @@ k8s.io/kube-aggregator v0.24.2/go.mod h1:Ju2jNDixn+vqeeKEBfjfpc204bO1pbdXX0N9knC k8s.io/kube-controller-manager v0.24.2/go.mod h1:KDE0yqiEvxYiO0WRpPA4rVx8AcK1vsWydUF37AJ9lTI= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kube-openapi v0.0.0-20230202010329-39b3636cbaa3 h1:vV3ZKAUX0nMjTflyfVea98dTfROpIxDaEsQws0FT2Ts= -k8s.io/kube-openapi v0.0.0-20230202010329-39b3636cbaa3/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= +k8s.io/kube-openapi v0.0.0-20230210211930-4b0756abdef5 h1:/zkKSeCtGRHYqRmrpa9uPYDWMpmQ5bZijBSoOpW384c= +k8s.io/kube-openapi v0.0.0-20230210211930-4b0756abdef5/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= k8s.io/kube-proxy v0.24.2/go.mod h1:bozS2ufl/Ns6s40Ue34eV7rqyLVygi5usSmCgW7rFU8= k8s.io/kube-scheduler v0.24.2/go.mod h1:DRa+aeXKSYUUOHHIc/9EcaO9+FW5FydaOfPSvaSW5Ko= k8s.io/kubectl v0.24.2 h1:+RfQVhth8akUmIc2Ge8krMl/pt66V7210ka3RE/p0J4= @@ -1712,8 +1647,8 @@ k8s.io/system-validators v1.7.0/go.mod h1:gP1Ky+R9wtrSiFbrpEPwWMeYz9yqyy1S/KOh0V k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20230202215443-34013725500c h1:YVqDar2X7YiQa/DVAXFMDIfGF8uGrHQemlrwRU5NlVI= -k8s.io/utils v0.0.0-20230202215443-34013725500c/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= +k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= diff --git a/go.mod b/go.mod index bb9a9453363..211f1f46069 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/Azure/go-autorest/autorest/adal v0.9.22 github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 - github.com/IBM/go-sdk-core/v5 v5.12.0 + github.com/IBM/go-sdk-core/v5 v5.12.1 github.com/IBM/secrets-manager-go-sdk v1.0.49 github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/sprig/v3 v3.2.3 @@ -48,17 +48,17 @@ require ( github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 github.com/akeylesslabs/akeyless-go/v2 v2.20.3 - github.com/aliyun/alibaba-cloud-sdk-go v1.62.155 - github.com/aws/aws-sdk-go v1.44.195 + github.com/aliyun/alibaba-cloud-sdk-go v1.62.164 + github.com/aws/aws-sdk-go v1.44.200 github.com/go-logr/logr v1.2.3 github.com/go-test/deep v1.0.4 // indirect github.com/google/go-cmp v0.5.9 github.com/google/uuid v1.3.0 github.com/googleapis/gax-go/v2 v2.7.0 - github.com/hashicorp/vault/api v1.8.3 - github.com/hashicorp/vault/api/auth/approle v0.3.0 - github.com/hashicorp/vault/api/auth/kubernetes v0.3.0 - github.com/hashicorp/vault/api/auth/ldap v0.3.0 + github.com/hashicorp/vault/api v1.9.0 + github.com/hashicorp/vault/api/auth/approle v0.4.0 + github.com/hashicorp/vault/api/auth/kubernetes v0.4.0 + github.com/hashicorp/vault/api/auth/ldap v0.4.0 github.com/huandu/xstrings v1.4.0 // indirect github.com/lestrrat-go/jwx v1.2.25 github.com/onsi/ginkgo/v2 v2.8.0 @@ -69,23 +69,23 @@ require ( github.com/spf13/cobra v1.6.1 github.com/stretchr/testify v1.8.1 github.com/tidwall/gjson v1.14.4 - github.com/xanzy/go-gitlab v0.79.1 - github.com/yandex-cloud/go-genproto v0.0.0-20230206132150-6ca32cf303b0 - github.com/yandex-cloud/go-sdk v0.0.0-20230206132606-87dc0cfe84bf + github.com/xanzy/go-gitlab v0.80.0 + github.com/yandex-cloud/go-genproto v0.0.0-20230213085250-850b3568e0c5 + github.com/yandex-cloud/go-sdk v0.0.0-20230213085834-eedd655a7e14 github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a go.uber.org/zap v1.24.0 - golang.org/x/crypto v0.5.0 - golang.org/x/oauth2 v0.4.0 + golang.org/x/crypto v0.6.0 + golang.org/x/oauth2 v0.5.0 google.golang.org/api v0.109.0 - google.golang.org/genproto v0.0.0-20230202175211-008b39050e57 // indirect - google.golang.org/grpc v1.52.3 + google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc // indirect + google.golang.org/grpc v1.53.0 gopkg.in/yaml.v3 v3.0.1 grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 k8s.io/api v0.26.1 k8s.io/apiextensions-apiserver v0.26.1 k8s.io/apimachinery v0.26.1 k8s.io/client-go v1.5.2 - k8s.io/utils v0.0.0-20230202215443-34013725500c + k8s.io/utils v0.0.0-20230209194617-a36077c30491 sigs.k8s.io/controller-runtime v0.14.4 sigs.k8s.io/controller-tools v0.11.3 ) @@ -96,14 +96,17 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 github.com/hashicorp/golang-lru v0.5.4 - github.com/keeper-security/secrets-manager-go/core v1.4.0 + github.com/keeper-security/secrets-manager-go/core v1.5.0 github.com/maxbrunsfeld/counterfeiter/v6 v6.6.1 github.com/sethvargo/go-password v0.2.0 github.com/spf13/pflag v1.0.5 sigs.k8s.io/yaml v1.3.0 ) -require cloud.google.com/go/compute/metadata v0.2.3 // indirect +require ( + cloud.google.com/go/compute/metadata v0.2.3 // indirect + github.com/rogpeppe/go-internal v1.9.0 // indirect +) require ( cloud.google.com/go/compute v1.18.0 // indirect @@ -117,8 +120,6 @@ require ( github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/Masterminds/semver/v3 v3.2.0 // indirect github.com/PaesslerAG/gval v1.2.2 // indirect - github.com/armon/go-metrics v0.4.1 // indirect - github.com/armon/go-radix v1.0.0 // indirect github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v3 v3.2.2 // indirect @@ -147,29 +148,21 @@ require ( github.com/golang-jwt/jwt/v4 v4.4.3 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/golang/snappy v0.0.4 // indirect github.com/google/gnostic v0.6.9 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.1 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-hclog v1.4.0 // indirect - github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.4.8 // indirect github.com/hashicorp/go-retryablehttp v0.7.2 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 // indirect github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect - github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/hcl v1.0.1-vault-5 // indirect - github.com/hashicorp/vault/sdk v0.7.0 // indirect - github.com/hashicorp/yamux v0.1.1 // indirect github.com/imdario/mergo v0.3.13 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect @@ -194,10 +187,8 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/oklog/run v1.1.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect - github.com/pierrec/lz4 v2.6.1+incompatible // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -212,18 +203,18 @@ require ( github.com/tidwall/pretty v1.2.1 // indirect github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect github.com/uber/jaeger-lib v2.4.1+incompatible // indirect - go.mongodb.org/mongo-driver v1.11.1 // indirect + go.mongodb.org/mongo-driver v1.11.2 // indirect go.opencensus.io v0.24.0 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/exp v0.0.0-20230206171751-46f607a40771 - golang.org/x/mod v0.7.0 // indirect - golang.org/x/net v0.5.0 // indirect + golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb + golang.org/x/mod v0.8.0 // indirect + golang.org/x/net v0.6.0 // indirect golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.4.0 // indirect - golang.org/x/text v0.6.0 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.5.0 // indirect + golang.org/x/tools v0.6.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect @@ -236,7 +227,7 @@ require ( k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9 // indirect k8s.io/klog v1.0.0 // indirect k8s.io/klog/v2 v2.90.0 // indirect - k8s.io/kube-openapi v0.0.0-20230202010329-39b3636cbaa3 // indirect + k8s.io/kube-openapi v0.0.0-20230210211930-4b0756abdef5 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/go.sum b/go.sum index 39852684ca6..9d199fe3608 100644 --- a/go.sum +++ b/go.sum @@ -86,11 +86,10 @@ github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7 github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= -github.com/IBM/go-sdk-core/v5 v5.12.0 h1:S7sSYQUe0f/xLh87ubwoXWQeUmRCwDNUv3qB4LMC0SI= -github.com/IBM/go-sdk-core/v5 v5.12.0/go.mod h1:WZPFasUzsKab/2mzt29xPcfruSk5js2ywAPwW4VJjdI= +github.com/IBM/go-sdk-core/v5 v5.12.1 h1:9hb9oosBma4+N05xmKmtAW13T1nfADMVYRE7fu06lZ0= +github.com/IBM/go-sdk-core/v5 v5.12.1/go.mod h1:WZPFasUzsKab/2mzt29xPcfruSk5js2ywAPwW4VJjdI= github.com/IBM/secrets-manager-go-sdk v1.0.49 h1:wRxyjFpSoZz6brj55JSMk6Sb38dLrQYnsEKcdYibflo= github.com/IBM/secrets-manager-go-sdk v1.0.49/go.mod h1:QyDSznC6gJEXIGaj+JPxoEVtyXfkaxzId87mxcEb+vM= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -113,29 +112,18 @@ github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 h1:vTckjyBhHOBiOWSC/oaEU2Oo4 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4/go.mod h1:As/RomC2w/fa3y+yHRlVHPmkbP+zrKBFRow41y5dk+E= github.com/akeylesslabs/akeyless-go/v2 v2.20.3 h1:NIRMynmpQbfgQyRLf5DMQC8p5iLgaUu1MXBB4ijLCxM= github.com/akeylesslabs/akeyless-go/v2 v2.20.3/go.mod h1:uOdXD49NCCe4rexeSc2aBU5Qv4KZgJE6YlbtYalvb+I= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.155 h1:qFWDgp7fsmkpfJZfpaTwppg9gptneYURTczlOP5lHI8= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.155/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.164 h1:1CaNFKN3P02nI0bbSfp4aY/rwHbu2Aot4Aj3YoUtw+s= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.164/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= -github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= -github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.44.195 h1:d5xFL0N83Fpsq2LFiHgtBUHknCRUPGHdOlCWt/jtOJs= -github.com/aws/aws-sdk-go v1.44.195/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.200 h1:JcFf/BnOaMWe9ObjaklgbbF0bGXI4XbYJwYn2eFNVyQ= +github.com/aws/aws-sdk-go v1.44.200/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= @@ -152,8 +140,6 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -187,19 +173,14 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= -github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= -github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -207,15 +188,9 @@ github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -241,7 +216,6 @@ github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/Nu github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= @@ -251,7 +225,6 @@ github.com/gobuffalo/flect v1.0.0/go.mod h1:l9V6xSb4BlXwsxEMj3FVEub2nkdQjWhPvD8X github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= @@ -294,8 +267,6 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= @@ -311,6 +282,7 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= @@ -341,8 +313,8 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.1 h1:RY7tHKZcRlk788d5WSo/e83gOyyy742E8GSs771ySpg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= @@ -351,54 +323,30 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v1.4.0 h1:ctuWFGrhFha8BnnzxqeRGidlEcQkDyL5u8J8t5eA11I= github.com/hashicorp/go-hclog v1.4.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= -github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-kms-wrapping/entropy/v2 v2.0.0/go.mod h1:xvb32K2keAc+R8DSFG2IwDcydK9DBQE+fGA5fsw6hSk= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= -github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM= -github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= -github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0= github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-secure-stdlib/base62 v0.1.1/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw= -github.com/hashicorp/go-secure-stdlib/mlock v0.1.1/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I= -github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 h1:p4AKXPPS24tO8Wc8i1gLvSKdmkiSY5xuju57czJ/IJQ= -github.com/hashicorp/go-secure-stdlib/mlock v0.1.2/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 h1:UpiO20jno/eV1eVZcxqWnUohyKRe1g8FPV/xH1s/2qs= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= -github.com/hashicorp/go-secure-stdlib/password v0.1.1/go.mod h1:9hH302QllNwu1o2TGYtSk8I8kTAN0ca1EHpwhm5Mmzo= github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= -github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs= github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= -github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= @@ -406,21 +354,14 @@ github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= -github.com/hashicorp/vault/api v1.8.0/go.mod h1:uJrw6D3y9Rv7hhmS17JQC50jbPDAZdjZoTtrCCxxs7E= -github.com/hashicorp/vault/api v1.8.3 h1:cHQOLcMhBR+aVI0HzhPxO62w2+gJhIrKguQNONPzu6o= -github.com/hashicorp/vault/api v1.8.3/go.mod h1:4g/9lj9lmuJQMtT6CmVMHC5FW1yENaVv+Nv4ZfG8fAg= -github.com/hashicorp/vault/api/auth/approle v0.3.0 h1:Ib0oCNXsCq/QZhPYtXPzJEbGS5WR/KoZf8c84QoFdkU= -github.com/hashicorp/vault/api/auth/approle v0.3.0/go.mod h1:hm51TbjzUkPO0Y17wkrpwOpvyyMRpXJNueTHiG04t3k= -github.com/hashicorp/vault/api/auth/kubernetes v0.3.0 h1:HkaCmTKzcgLa2tjdiAid1rbmyQNmQGHfnmvIIM2WorY= -github.com/hashicorp/vault/api/auth/kubernetes v0.3.0/go.mod h1:l1B4MGtLc+P37MabBQiIhP3qd9agj0vqhETmaQjjC/Y= -github.com/hashicorp/vault/api/auth/ldap v0.3.0 h1:G2Hk03lwqaeHcjBmYtR+aHDzttw5qE3r3oQr+F4O7Ro= -github.com/hashicorp/vault/api/auth/ldap v0.3.0/go.mod h1:WhIWEHgzyr99FQbna94Y0twKmz3sbtPGbVtIy40Oyik= -github.com/hashicorp/vault/sdk v0.6.0/go.mod h1:+DRpzoXIdMvKc88R4qxr+edwy/RvH5QK8itmxLiDHLc= -github.com/hashicorp/vault/sdk v0.7.0 h1:2pQRO40R1etpKkia5fb4kjrdYMx3BHklPxl1pxpxDHg= -github.com/hashicorp/vault/sdk v0.7.0/go.mod h1:KyfArJkhooyba7gYCKSq8v66QdqJmnbAxtV/OX1+JTs= -github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= -github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/hashicorp/vault/api v1.9.0 h1:ab7dI6W8DuCY7yCU8blo0UCYl2oHre/dloCmzMWg9w8= +github.com/hashicorp/vault/api v1.9.0/go.mod h1:lloELQP4EyhjnCQhF8agKvWIVTmxbpEJj70b98959sM= +github.com/hashicorp/vault/api/auth/approle v0.4.0 h1:tjJHoUkPx8zRoFlFy86uvgg/1gpTnDPp0t0BYWTKjjw= +github.com/hashicorp/vault/api/auth/approle v0.4.0/go.mod h1:D2gEpR0aS/F/MEcSjmhUlOsuK1RMVZojsnIQAEf0EV0= +github.com/hashicorp/vault/api/auth/kubernetes v0.4.0 h1:f6OIOF9012JIdqYvOeeewxhtQdJosnog2CHzh33j41s= +github.com/hashicorp/vault/api/auth/kubernetes v0.4.0/go.mod h1:tMewM2hPyFNKP1EXdWbc0dUHHoS5V/0qS04BEaxuy78= +github.com/hashicorp/vault/api/auth/ldap v0.4.0 h1:/P2HCNmcDY6s22JBXxVhr9noaFqPEQS2qwSnWIYezkc= +github.com/hashicorp/vault/api/auth/ldap v0.4.0/go.mod h1:RJawcFnbfk3zyB9lDbFeGT5YkaAoWTpACEApFt5/TU0= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= @@ -434,8 +375,6 @@ github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= -github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= @@ -444,21 +383,16 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/keeper-security/secrets-manager-go/core v1.4.0 h1:6x65lMBPwHNirQRXwGByCHrzJx7LDWt06uBUKCLs92w= -github.com/keeper-security/secrets-manager-go/core v1.4.0/go.mod h1:dtlaeeds9+SZsbDAZnQRsDSqEAK9a62SYtqhNql+VgQ= +github.com/keeper-security/secrets-manager-go/core v1.5.0 h1:8cPzRWjIXNvhw9VC/1lZL26apmZYPtwUuUtKLV0Tw/c= +github.com/keeper-security/secrets-manager-go/core v1.5.0/go.mod h1:dtlaeeds9+SZsbDAZnQRsDSqEAK9a62SYtqhNql+VgQ= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -503,7 +437,6 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.6.1 h1:9XE5ykDiC8eNSqIPkxx0EsV3kMX1oe4kQWRZjIgytUA= @@ -514,7 +447,6 @@ github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa1 github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= @@ -529,21 +461,16 @@ github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= -github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -565,43 +492,27 @@ github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:Ff github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= github.com/oracle/oci-go-sdk/v56 v56.1.0 h1:HOr9P+MkwgrilEGTJCU7a6GMFrUG/RZAzvh/2JeRXvI= github.com/oracle/oci-go-sdk/v56 v56.1.0/go.mod h1:kDJAL3HEAF+4oQR8GfaOkY6rz2kU3/kZ6vYJnJXSCkA= -github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= -github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -615,8 +526,6 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sony/gobreaker v0.4.2-0.20210216022020-dd874f9dd33b/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg= github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= @@ -630,7 +539,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -653,23 +561,22 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/xanzy/go-gitlab v0.79.1 h1:ZmEei8RZYlqk4D7nYrWWZqywmKBOd7vmPMlJbueZXUU= -github.com/xanzy/go-gitlab v0.79.1/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M= +github.com/xanzy/go-gitlab v0.80.0 h1:2d6RwUrI3ZC2Xh9urnqiiHCLzWNndrGtje3yByZubdQ= +github.com/xanzy/go-gitlab v0.80.0/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/yandex-cloud/go-genproto v0.0.0-20230206132150-6ca32cf303b0 h1:Agj+9yFgZYa7ojWmcXNHy83WZ//Qz1RzSRZRaNmIi3Q= -github.com/yandex-cloud/go-genproto v0.0.0-20230206132150-6ca32cf303b0/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= -github.com/yandex-cloud/go-sdk v0.0.0-20230206132606-87dc0cfe84bf h1:jjy3J5XOv2LsD60IOJOYjhyWYaV2UNudbo5xDUucrjo= -github.com/yandex-cloud/go-sdk v0.0.0-20230206132606-87dc0cfe84bf/go.mod h1:ZXQgvDrguV3h/Ir0AqvC/ktopsKBiHORacW9lbi934k= +github.com/yandex-cloud/go-genproto v0.0.0-20230213085250-850b3568e0c5 h1:dFinCaaTET9YTJjq1jC/V1AEFtya/dzuTO8fpB7jrAY= +github.com/yandex-cloud/go-genproto v0.0.0-20230213085250-850b3568e0c5/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= +github.com/yandex-cloud/go-sdk v0.0.0-20230213085834-eedd655a7e14 h1:2yNVc+wIhp8SwyXdmbxGl7vT47oJWYxYxmRzReUelZM= +github.com/yandex-cloud/go-sdk v0.0.0-20230213085834-eedd655a7e14/go.mod h1:iICjK1Tf7LbahA6tJJ4akCHKnTjeGP+ceQKsjtWOiyo= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= @@ -679,8 +586,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= -go.mongodb.org/mongo-driver v1.11.1 h1:QP0znIRTuL0jf1oBQoAoM0C6ZJfBK4kx0Uumtv1A7w8= -go.mongodb.org/mongo-driver v1.11.1/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= +go.mongodb.org/mongo-driver v1.11.2 h1:+1v2rDQUWNcGW7/7E0Jvdz51V38XXxJfhzbV17aNHCw= +go.mongodb.org/mongo-driver v1.11.2/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -703,22 +610,21 @@ go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTV go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -732,8 +638,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= -golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w= +golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -759,13 +665,11 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -773,7 +677,6 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -807,8 +710,9 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -821,8 +725,8 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -838,14 +742,11 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -899,14 +800,16 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -917,8 +820,9 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -979,8 +883,8 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4= -golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1023,7 +927,6 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1067,9 +970,8 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230202175211-008b39050e57 h1:vArvWooPH749rNHpBGgVl+U9B9dATjiEhJzcWGlovNs= -google.golang.org/genproto v0.0.0-20230202175211-008b39050e57/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc h1:ijGwO+0vL2hJt5gaygqP2j6PfflOBrRot0IczKbmtio= +google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1092,8 +994,8 @@ google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= -google.golang.org/grpc v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ= -google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1109,7 +1011,6 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1132,11 +1033,9 @@ gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -1176,10 +1075,10 @@ k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.90.0 h1:VkTxIV/FjRXn1fgNNcKGM8cfmL1Z33ZjXRTVxKCoF5M= k8s.io/klog/v2 v2.90.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20230202010329-39b3636cbaa3 h1:vV3ZKAUX0nMjTflyfVea98dTfROpIxDaEsQws0FT2Ts= -k8s.io/kube-openapi v0.0.0-20230202010329-39b3636cbaa3/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= -k8s.io/utils v0.0.0-20230202215443-34013725500c h1:YVqDar2X7YiQa/DVAXFMDIfGF8uGrHQemlrwRU5NlVI= -k8s.io/utils v0.0.0-20230202215443-34013725500c/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-openapi v0.0.0-20230210211930-4b0756abdef5 h1:/zkKSeCtGRHYqRmrpa9uPYDWMpmQ5bZijBSoOpW384c= +k8s.io/kube-openapi v0.0.0-20230210211930-4b0756abdef5/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= +k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= +k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= diff --git a/terraform/aws/modules/cluster/main.tf b/terraform/aws/modules/cluster/main.tf index 949d858c234..369d06455c2 100644 --- a/terraform/aws/modules/cluster/main.tf +++ b/terraform/aws/modules/cluster/main.tf @@ -81,9 +81,9 @@ module "vpc" { single_nat_gateway = true enable_dns_hostnames = true - enable_flow_log = true - create_flow_log_cloudwatch_iam_role = true - create_flow_log_cloudwatch_log_group = true + enable_flow_log = false + create_flow_log_cloudwatch_iam_role = false + create_flow_log_cloudwatch_log_group = false public_subnet_tags = { "kubernetes.io/cluster/${local.name}" = "shared" From d2e1aa7156c7e5785d895ab574c65ad4de4a411e Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Tue, 14 Feb 2023 22:57:06 +0100 Subject: [PATCH 21/62] feat: add pr template (#2011) Signed-off-by: Moritz Johner --- .github/pull_request_template.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000000..4d5867b9b5c --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,19 @@ +## Problem Statement + +What is the problem you're trying to solve? + +## Related Issue + +Fixes #... + +## Proposed Changes + +How do you like to solve the issue and why? + +## Checklist + +- [ ] I have read the [contribution guidelines](https://external-secrets.io/latest/contributing/process/#submitting-a-pull-request) +- [ ] All commits are signed with `git commit --signoff` +- [ ] My changes have reasonable test coverage +- [ ] All tests pass with `make test` +- [ ] I ensured my PR is ready for review with `make reviewable` From 2acc637106bdea4d55a86b5433b1481c7a818aa1 Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Tue, 14 Feb 2023 22:57:31 +0100 Subject: [PATCH 22/62] fix: pass tenantID correctly to acr generator (#2010) Signed-off-by: Moritz Johner --- docs/api/generator/acr.md | 28 ++++++++++++++++++++++++++++ pkg/generator/acr/acr.go | 6 +++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/docs/api/generator/acr.md b/docs/api/generator/acr.md index 3b2eb9378df..7bc18ab0c1a 100644 --- a/docs/api/generator/acr.md +++ b/docs/api/generator/acr.md @@ -47,3 +47,31 @@ repository:my-repository:pull {% include 'generator-acr.yaml' %} ``` +```yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: azurecr-credentials +spec: + dataFrom: + - sourceRef: + generatorRef: + apiVersion: generators.external-secrets.io/v1alpha1 + kind: ACRAccessToken + name: myregistry.azurecr.io + refreshInterval: 12h + target: + name: azurecr-credentials + template: + type: kubernetes.io/dockerconfigjson + data: + .dockerconfigjson: | + { + "auths": { + "myregistry.azurecr.io": { + "username": "{{ .username }}", + "identitytoken": "{{ .password }}", + } + } + } +``` \ No newline at end of file diff --git a/pkg/generator/acr/acr.go b/pkg/generator/acr/acr.go index ee0fe747bb7..2aaea5731b6 100644 --- a/pkg/generator/acr/acr.go +++ b/pkg/generator/acr/acr.go @@ -80,7 +80,7 @@ func (g *Generator) Generate(ctx context.Context, jsonSpec *apiextensions.JSON, return nil, err } g.clientSecretCreds = func(tenantID, clientID, clientSecret string, options *azidentity.ClientSecretCredentialOptions) (TokenGetter, error) { - return azidentity.NewClientSecretCredential(clientID, clientID, clientSecret, options) + return azidentity.NewClientSecretCredential(tenantID, clientID, clientSecret, options) } return g.generate( @@ -175,7 +175,7 @@ func fetchACRAccessToken(acrRefreshToken, tenantID, registryURL, scope string) ( } defer res.Body.Close() if res.StatusCode != http.StatusOK { - return "", fmt.Errorf("unexpected status code: %d", res.StatusCode) + return "", fmt.Errorf("could not generate access token, unexpected status code: %d", res.StatusCode) } body, err := io.ReadAll(res.Body) if err != nil { @@ -210,7 +210,7 @@ func fetchACRRefreshToken(aadAccessToken, tenantID, registryURL string) (string, } defer res.Body.Close() if res.StatusCode != http.StatusOK { - return "", fmt.Errorf("unexpected status code %d, expected %d", res.StatusCode, http.StatusOK) + return "", fmt.Errorf("count not generate refresh token, unexpected status code %d, expected %d", res.StatusCode, http.StatusOK) } body, err := io.ReadAll(res.Body) if err != nil { From 39c8a49bfb27ce5f9c60d65ac27603ebc745fa01 Mon Sep 17 00:00:00 2001 From: Matheus Tosta Date: Fri, 17 Feb 2023 14:29:59 -0400 Subject: [PATCH 23/62] fix typo in the full-pushsecret.yaml (#2019) * fix typo in the full-pushsecret.yaml * change the array reference of the remoteKey from the full-pushsecret.yaml to a map reference --- docs/snippets/full-pushsecret.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/snippets/full-pushsecret.yaml b/docs/snippets/full-pushsecret.yaml index 2f651b46335..def8ef5da8a 100644 --- a/docs/snippets/full-pushsecret.yaml +++ b/docs/snippets/full-pushsecret.yaml @@ -14,5 +14,5 @@ spec: data: - match: secretKey: best-pokemon # Source Kubernetes secret key to be pushed - remoteRefs: - - remoteKey: my-first-parameter # Remote reference (where the secret is going to be pushed) + remoteRef: + remoteKey: my-first-parameter # Remote reference (where the secret is going to be pushed) From 6a5d3482dca437496d5866d3ef6deb3abedc385e Mon Sep 17 00:00:00 2001 From: Charles Wimmer Date: Fri, 17 Feb 2023 10:31:19 -0800 Subject: [PATCH 24/62] :sparkles: Add PushSecret CRD to kustomization.yaml (#2021) Signed-off-by: Charles Wimmer --- config/crds/bases/kustomization.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/crds/bases/kustomization.yaml b/config/crds/bases/kustomization.yaml index e6bf5c7d8f9..0f86d9104d0 100644 --- a/config/crds/bases/kustomization.yaml +++ b/config/crds/bases/kustomization.yaml @@ -5,6 +5,7 @@ resources: - external-secrets.io_clusterexternalsecrets.yaml - external-secrets.io_clustersecretstores.yaml - external-secrets.io_externalsecrets.yaml + - external-secrets.io_pushsecrets.yaml - external-secrets.io_secretstores.yaml - generators.external-secrets.io_acraccesstokens.yaml - generators.external-secrets.io_ecrauthorizationtokens.yaml From 409f18b9649598525015ce494fbe4c51130812e9 Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Mon, 20 Feb 2023 11:03:07 +0100 Subject: [PATCH 25/62] :broom: bump deps (#2032) Signed-off-by: Moritz Johner --- Makefile | 6 ++++++ e2e/go.mod | 22 +++++++++++----------- e2e/go.sum | 44 ++++++++++++++++++++++---------------------- go.mod | 22 +++++++++++----------- go.sum | 44 ++++++++++++++++++++++---------------------- 5 files changed, 72 insertions(+), 66 deletions(-) diff --git a/Makefile b/Makefile index f8cd72f5bb6..2c96695c157 100644 --- a/Makefile +++ b/Makefile @@ -81,6 +81,12 @@ check-diff: reviewable ## Ensure branch is clean. @test -z "$$(git status --porcelain)" || (echo "$$(git status --porcelain)" && $(FAIL)) @$(OK) branch is clean +update-deps: + go get -u + cd e2e && go get -u + @go mod tidy + @cd e2e/ && go mod tidy + # ==================================================================================== # Golang diff --git a/e2e/go.mod b/e2e/go.mod index 0dd1d052e1c..81c75798b60 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -43,21 +43,21 @@ require ( github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 github.com/akeylesslabs/akeyless-go/v2 v2.20.3 - github.com/aliyun/alibaba-cloud-sdk-go v1.62.164 + github.com/aliyun/alibaba-cloud-sdk-go v1.62.174 github.com/argoproj/argo-cd/v2 v2.4.8 - github.com/aws/aws-sdk-go v1.44.200 + github.com/aws/aws-sdk-go v1.44.204 github.com/external-secrets/external-secrets v0.0.0 github.com/fluxcd/helm-controller/api v0.22.2 github.com/fluxcd/pkg/apis/meta v0.14.2 github.com/fluxcd/source-controller/api v0.25.11 - github.com/golang-jwt/jwt/v4 v4.4.3 + github.com/golang-jwt/jwt/v4 v4.5.0 github.com/hashicorp/vault/api v1.9.0 - github.com/onsi/ginkgo/v2 v2.8.1 - github.com/onsi/gomega v1.26.0 + github.com/onsi/ginkgo/v2 v2.8.3 + github.com/onsi/gomega v1.27.0 github.com/oracle/oci-go-sdk/v56 v56.1.0 - github.com/xanzy/go-gitlab v0.80.0 + github.com/xanzy/go-gitlab v0.80.2 golang.org/x/oauth2 v0.5.0 - google.golang.org/api v0.109.0 + google.golang.org/api v0.110.0 k8s.io/api v0.26.1 k8s.io/apiextensions-apiserver v0.26.1 k8s.io/apimachinery v0.26.1 @@ -70,7 +70,7 @@ require ( require ( cloud.google.com/go/compute v1.18.0 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v0.10.0 // indirect + cloud.google.com/go/iam v0.12.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.28 // indirect @@ -198,7 +198,7 @@ require ( go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect golang.org/x/crypto v0.6.0 // indirect golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb // indirect - golang.org/x/net v0.6.0 // indirect + golang.org/x/net v0.7.0 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/term v0.5.0 // indirect @@ -207,7 +207,7 @@ require ( golang.org/x/tools v0.6.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc // indirect + google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44 // indirect google.golang.org/grpc v1.53.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect @@ -223,7 +223,7 @@ require ( k8s.io/component-helpers v0.24.2 // indirect k8s.io/klog/v2 v2.90.0 // indirect k8s.io/kube-aggregator v0.24.2 // indirect - k8s.io/kube-openapi v0.0.0-20230210211930-4b0756abdef5 // indirect + k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d // indirect k8s.io/kubectl v0.24.2 // indirect k8s.io/kubernetes v1.24.2 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/e2e/go.sum b/e2e/go.sum index 7e0ec8c1ea3..1960e940b7e 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -34,8 +34,8 @@ cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2Aawl cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/iam v0.10.0 h1:fpP/gByFs6US1ma53v7VxhvbJpO2Aapng6wabJ99MuI= -cloud.google.com/go/iam v0.10.0/go.mod h1:nXAECrMt2qHpF6RZUZseteD6QyanL68reN4OXPw0UWM= +cloud.google.com/go/iam v0.12.0 h1:DRtTY29b75ciH6Ov1PHb4/iat2CLCvrOm40Q0a6DFpE= +cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= @@ -125,8 +125,8 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI= github.com/alicebob/miniredis/v2 v2.14.2 h1:VeoqKUAsJfT2af61nDE7qhBzqn3J6xjnt9MFAbdrEtg= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.164 h1:1CaNFKN3P02nI0bbSfp4aY/rwHbu2Aot4Aj3YoUtw+s= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.164/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.174 h1:K5561f5qv64GmtQuY0OtkY0H2x1bTXBeYwwWFPzc4D8= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.174/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -154,8 +154,8 @@ github.com/aws/aws-sdk-go v1.33.16/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZve github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= github.com/aws/aws-sdk-go v1.38.49/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.44.200 h1:JcFf/BnOaMWe9ObjaklgbbF0bGXI4XbYJwYn2eFNVyQ= -github.com/aws/aws-sdk-go v1.44.200/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.204 h1:7/tPUXfNOHB390A63t6fJIwmlwVQAkAwcbzKsU2/6OQ= +github.com/aws/aws-sdk-go v1.44.204/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -395,8 +395,8 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.4.3 h1:Hxl6lhQFj4AnOX6MLrsCb/+7tCj7DxP7VA+2rDIq5AU= -github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= @@ -742,15 +742,15 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.8.1 h1:xFTEVwOFa1D/Ty24Ws1npBWkDYEV9BqZrsDxVrVkrrU= -github.com/onsi/ginkgo/v2 v2.8.1/go.mod h1:N1/NbDngAFcSLdyZ+/aYTYGSlq9qMCS/cNKGJjy+csc= +github.com/onsi/ginkgo/v2 v2.8.3 h1:RpbK1G8nWPNaCVFBWsOGnEQQGgASi6b8fxcWBvDYjxQ= +github.com/onsi/ginkgo/v2 v2.8.3/go.mod h1:6OaUA8BCi0aZfmzYT/q9AacwTzDpNbxILUT+TlBq6MY= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= -github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= -github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= +github.com/onsi/gomega v1.27.0 h1:QLidEla4bXUuZVFa4KX6JHCsuGgbi85LC/pCHrt/O08= +github.com/onsi/gomega v1.27.0/go.mod h1:i189pavgK95OSIipFBa74gC2V4qrQuvjuyGEr3GmbXA= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -955,8 +955,8 @@ github.com/vmihailenco/msgpack/v5 v5.3.4/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= -github.com/xanzy/go-gitlab v0.80.0 h1:2d6RwUrI3ZC2Xh9urnqiiHCLzWNndrGtje3yByZubdQ= -github.com/xanzy/go-gitlab v0.80.0/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M= +github.com/xanzy/go-gitlab v0.80.2 h1:CH1Q7NDklqZllox4ICVF4PwlhQGfPtE+w08Jsb74ZX0= +github.com/xanzy/go-gitlab v0.80.2/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -1168,8 +1168,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1425,8 +1425,8 @@ google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.45.0/go.mod h1:ISLIJCedJolbZvDfAk+Ctuq5hf+aJ33WgtUsfyFoLXA= google.golang.org/api v0.46.0/go.mod h1:ceL4oozhkAiTID8XMmJBsIxID/9wMXJVVFXPg4ylg3I= -google.golang.org/api v0.109.0 h1:sW9hgHyX497PP5//NUM7nqfV8D0iDfBApqq7sOh1XR8= -google.golang.org/api v0.109.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.110.0 h1:l+rh0KYUooe9JGbGVx71tbFo4SMbMTXK3I3ia2QSEeU= +google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1486,8 +1486,8 @@ google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc h1:ijGwO+0vL2hJt5gaygqP2j6PfflOBrRot0IczKbmtio= -google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44 h1:EfLuoKW5WfkgVdDy7dTK8qSbH37AX5mj/MFh+bGPz14= +google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1629,8 +1629,8 @@ k8s.io/kube-aggregator v0.24.2/go.mod h1:Ju2jNDixn+vqeeKEBfjfpc204bO1pbdXX0N9knC k8s.io/kube-controller-manager v0.24.2/go.mod h1:KDE0yqiEvxYiO0WRpPA4rVx8AcK1vsWydUF37AJ9lTI= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kube-openapi v0.0.0-20230210211930-4b0756abdef5 h1:/zkKSeCtGRHYqRmrpa9uPYDWMpmQ5bZijBSoOpW384c= -k8s.io/kube-openapi v0.0.0-20230210211930-4b0756abdef5/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= +k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d h1:oFDpQ7FfzinCtrFOl4izwOWsdTprlS2A9IXBENMW0UA= +k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= k8s.io/kube-proxy v0.24.2/go.mod h1:bozS2ufl/Ns6s40Ue34eV7rqyLVygi5usSmCgW7rFU8= k8s.io/kube-scheduler v0.24.2/go.mod h1:DRa+aeXKSYUUOHHIc/9EcaO9+FW5FydaOfPSvaSW5Ko= k8s.io/kubectl v0.24.2 h1:+RfQVhth8akUmIc2Ge8krMl/pt66V7210ka3RE/p0J4= diff --git a/go.mod b/go.mod index 211f1f46069..e042f88360d 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ replace ( ) require ( - cloud.google.com/go/iam v0.10.0 + cloud.google.com/go/iam v0.12.0 cloud.google.com/go/secretmanager v1.10.0 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible github.com/Azure/go-autorest/autorest v0.11.28 @@ -48,8 +48,8 @@ require ( github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 github.com/akeylesslabs/akeyless-go/v2 v2.20.3 - github.com/aliyun/alibaba-cloud-sdk-go v1.62.164 - github.com/aws/aws-sdk-go v1.44.200 + github.com/aliyun/alibaba-cloud-sdk-go v1.62.174 + github.com/aws/aws-sdk-go v1.44.204 github.com/go-logr/logr v1.2.3 github.com/go-test/deep v1.0.4 // indirect github.com/google/go-cmp v0.5.9 @@ -61,23 +61,23 @@ require ( github.com/hashicorp/vault/api/auth/ldap v0.4.0 github.com/huandu/xstrings v1.4.0 // indirect github.com/lestrrat-go/jwx v1.2.25 - github.com/onsi/ginkgo/v2 v2.8.0 - github.com/onsi/gomega v1.26.0 + github.com/onsi/ginkgo/v2 v2.8.3 + github.com/onsi/gomega v1.27.0 github.com/oracle/oci-go-sdk/v56 v56.1.0 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 github.com/spf13/cobra v1.6.1 github.com/stretchr/testify v1.8.1 github.com/tidwall/gjson v1.14.4 - github.com/xanzy/go-gitlab v0.80.0 + github.com/xanzy/go-gitlab v0.80.2 github.com/yandex-cloud/go-genproto v0.0.0-20230213085250-850b3568e0c5 github.com/yandex-cloud/go-sdk v0.0.0-20230213085834-eedd655a7e14 github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a go.uber.org/zap v1.24.0 golang.org/x/crypto v0.6.0 golang.org/x/oauth2 v0.5.0 - google.golang.org/api v0.109.0 - google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc // indirect + google.golang.org/api v0.110.0 + google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44 // indirect google.golang.org/grpc v1.53.0 gopkg.in/yaml.v3 v3.0.1 grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 @@ -145,7 +145,7 @@ require ( github.com/gobuffalo/flect v1.0.0 // indirect github.com/goccy/go-json v0.10.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.4.3 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/gnostic v0.6.9 // indirect @@ -209,7 +209,7 @@ require ( go.uber.org/multierr v1.9.0 // indirect golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb golang.org/x/mod v0.8.0 // indirect - golang.org/x/net v0.6.0 // indirect + golang.org/x/net v0.7.0 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/term v0.5.0 // indirect golang.org/x/text v0.7.0 // indirect @@ -227,7 +227,7 @@ require ( k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9 // indirect k8s.io/klog v1.0.0 // indirect k8s.io/klog/v2 v2.90.0 // indirect - k8s.io/kube-openapi v0.0.0-20230210211930-4b0756abdef5 // indirect + k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/go.sum b/go.sum index 9d199fe3608..fe9d5795998 100644 --- a/go.sum +++ b/go.sum @@ -31,8 +31,8 @@ cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGB cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v0.10.0 h1:fpP/gByFs6US1ma53v7VxhvbJpO2Aapng6wabJ99MuI= -cloud.google.com/go/iam v0.10.0/go.mod h1:nXAECrMt2qHpF6RZUZseteD6QyanL68reN4OXPw0UWM= +cloud.google.com/go/iam v0.12.0 h1:DRtTY29b75ciH6Ov1PHb4/iat2CLCvrOm40Q0a6DFpE= +cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= @@ -112,16 +112,16 @@ github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 h1:vTckjyBhHOBiOWSC/oaEU2Oo4 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4/go.mod h1:As/RomC2w/fa3y+yHRlVHPmkbP+zrKBFRow41y5dk+E= github.com/akeylesslabs/akeyless-go/v2 v2.20.3 h1:NIRMynmpQbfgQyRLf5DMQC8p5iLgaUu1MXBB4ijLCxM= github.com/akeylesslabs/akeyless-go/v2 v2.20.3/go.mod h1:uOdXD49NCCe4rexeSc2aBU5Qv4KZgJE6YlbtYalvb+I= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.164 h1:1CaNFKN3P02nI0bbSfp4aY/rwHbu2Aot4Aj3YoUtw+s= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.164/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.174 h1:K5561f5qv64GmtQuY0OtkY0H2x1bTXBeYwwWFPzc4D8= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.174/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.44.200 h1:JcFf/BnOaMWe9ObjaklgbbF0bGXI4XbYJwYn2eFNVyQ= -github.com/aws/aws-sdk-go v1.44.200/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.204 h1:7/tPUXfNOHB390A63t6fJIwmlwVQAkAwcbzKsU2/6OQ= +github.com/aws/aws-sdk-go v1.44.204/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -231,8 +231,8 @@ github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptG github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.4.3 h1:Hxl6lhQFj4AnOX6MLrsCb/+7tCj7DxP7VA+2rDIq5AU= -github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -479,14 +479,14 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI= -github.com/onsi/ginkgo/v2 v2.8.0/go.mod h1:6JsQiECmxCa3V5st74AL/AmsV482EDdVrGaVW6z3oYU= +github.com/onsi/ginkgo/v2 v2.8.3 h1:RpbK1G8nWPNaCVFBWsOGnEQQGgASi6b8fxcWBvDYjxQ= +github.com/onsi/ginkgo/v2 v2.8.3/go.mod h1:6OaUA8BCi0aZfmzYT/q9AacwTzDpNbxILUT+TlBq6MY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.0/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= -github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= +github.com/onsi/gomega v1.27.0 h1:QLidEla4bXUuZVFa4KX6JHCsuGgbi85LC/pCHrt/O08= +github.com/onsi/gomega v1.27.0/go.mod h1:i189pavgK95OSIipFBa74gC2V4qrQuvjuyGEr3GmbXA= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= @@ -565,8 +565,8 @@ github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaO github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/xanzy/go-gitlab v0.80.0 h1:2d6RwUrI3ZC2Xh9urnqiiHCLzWNndrGtje3yByZubdQ= -github.com/xanzy/go-gitlab v0.80.0/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M= +github.com/xanzy/go-gitlab v0.80.2 h1:CH1Q7NDklqZllox4ICVF4PwlhQGfPtE+w08Jsb74ZX0= +github.com/xanzy/go-gitlab v0.80.2/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= @@ -711,8 +711,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -917,8 +917,8 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.45.0/go.mod h1:ISLIJCedJolbZvDfAk+Ctuq5hf+aJ33WgtUsfyFoLXA= -google.golang.org/api v0.109.0 h1:sW9hgHyX497PP5//NUM7nqfV8D0iDfBApqq7sOh1XR8= -google.golang.org/api v0.109.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.110.0 h1:l+rh0KYUooe9JGbGVx71tbFo4SMbMTXK3I3ia2QSEeU= +google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -970,8 +970,8 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc h1:ijGwO+0vL2hJt5gaygqP2j6PfflOBrRot0IczKbmtio= -google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44 h1:EfLuoKW5WfkgVdDy7dTK8qSbH37AX5mj/MFh+bGPz14= +google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1075,8 +1075,8 @@ k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.90.0 h1:VkTxIV/FjRXn1fgNNcKGM8cfmL1Z33ZjXRTVxKCoF5M= k8s.io/klog/v2 v2.90.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20230210211930-4b0756abdef5 h1:/zkKSeCtGRHYqRmrpa9uPYDWMpmQ5bZijBSoOpW384c= -k8s.io/kube-openapi v0.0.0-20230210211930-4b0756abdef5/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= +k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d h1:oFDpQ7FfzinCtrFOl4izwOWsdTprlS2A9IXBENMW0UA= +k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= From f1f6bf1931bfe29cfdc1c6e5097b12a1e00464f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 11:06:07 +0100 Subject: [PATCH 26/62] chore(deps): bump golang from 1.20.0-alpine to 1.20.1-alpine (#2026) Bumps golang from 1.20.0-alpine to 1.20.1-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile.standalone | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.standalone b/Dockerfile.standalone index 7f4c5a9641f..3a32e89e98c 100644 --- a/Dockerfile.standalone +++ b/Dockerfile.standalone @@ -1,6 +1,6 @@ # This version of Dockerfile is for building without external dependencies. # Build a multi-platform image e.g. `docker buildx build --push --platform linux/arm64,linux/amd64 --tag external-secrets:dev --file Dockerfile.standalone .` -FROM golang:1.20.0-alpine AS builder +FROM golang:1.20.1-alpine AS builder ARG TARGETOS ARG TARGETARCH ENV CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} From 1cfca77b9be895e439e26f1dafcbc90589aee1be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20G=C3=B3mez?= <1637983+sebagomez@users.noreply.github.com> Date: Tue, 21 Feb 2023 14:55:03 -0300 Subject: [PATCH 27/62] :sparkles: Add MetadataPolicy=Fetch for AWS Secret Manager (#2025) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Get all the properties Signed-off-by: Sebastián Gómez * Add secrets to the cache Signed-off-by: Sebastián Gómez * First set of tests Signed-off-by: Sebastián Gómez * Last set of tests added Signed-off-by: Sebastián Gómez * Fixed lint issues Signed-off-by: Sebastián Gómez * Improved Tags to string mechanism Signed-off-by: Sebastián Gómez * Fix lint complain Signed-off-by: Sebastián Gómez --------- Signed-off-by: Sebastián Gómez Co-authored-by: Moritz Johner --- .../aws/secretsmanager/secretsmanager.go | 84 ++++++++++++++----- .../aws/secretsmanager/secretsmanager_test.go | 62 ++++++++++++++ 2 files changed, 127 insertions(+), 19 deletions(-) diff --git a/pkg/provider/aws/secretsmanager/secretsmanager.go b/pkg/provider/aws/secretsmanager/secretsmanager.go index 03a0d311d2b..2e94b969902 100644 --- a/pkg/provider/aws/secretsmanager/secretsmanager.go +++ b/pkg/provider/aws/secretsmanager/secretsmanager.go @@ -77,43 +77,89 @@ func New(sess *session.Session, cfg *aws.Config, referentAuth bool) (*SecretsMan }, nil } -func (sm *SecretsManager) fetch(_ context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (*awssm.GetSecretValueOutput, error) { +func (sm *SecretsManager) fetch(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (*awssm.GetSecretValueOutput, error) { ver := "AWSCURRENT" + valueFrom := "SECRET" if ref.Version != "" { ver = ref.Version } - log.Info("fetching secret value", "key", ref.Key, "version", ver) + if ref.MetadataPolicy == esv1beta1.ExternalSecretMetadataPolicyFetch { + valueFrom = "TAG" + } + + log.Info("fetching secret value", "key", ref.Key, "version", ver, "value", valueFrom) - cacheKey := fmt.Sprintf("%s#%s", ref.Key, ver) + cacheKey := fmt.Sprintf("%s#%s#%s", ref.Key, ver, valueFrom) if secretOut, found := sm.cache[cacheKey]; found { log.Info("found secret in cache", "key", ref.Key, "version", ver) return secretOut, nil } - var getSecretValueInput *awssm.GetSecretValueInput - if strings.HasPrefix(ver, "uuid/") { - versionID := strings.TrimPrefix(ver, "uuid/") - getSecretValueInput = &awssm.GetSecretValueInput{ - SecretId: &ref.Key, - VersionId: &versionID, + var secretOut *awssm.GetSecretValueOutput + var err error + + if ref.MetadataPolicy == esv1beta1.ExternalSecretMetadataPolicyFetch { + describeSecretInput := &awssm.DescribeSecretInput{ + SecretId: &ref.Key, + } + + descOutput, err := sm.client.DescribeSecretWithContext(ctx, describeSecretInput) + if err != nil { + return nil, err + } + log.Info("found metadata secret", "key", ref.Key, "output", descOutput) + + jsonTags, err := TagsToJSONString(descOutput.Tags) + if err != nil { + return nil, err + } + secretOut = &awssm.GetSecretValueOutput{ + ARN: descOutput.ARN, + CreatedDate: descOutput.CreatedDate, + Name: descOutput.Name, + SecretString: &jsonTags, + VersionId: &ver, } } else { - getSecretValueInput = &awssm.GetSecretValueInput{ - SecretId: &ref.Key, - VersionStage: &ver, + var getSecretValueInput *awssm.GetSecretValueInput + if strings.HasPrefix(ver, "uuid/") { + versionID := strings.TrimPrefix(ver, "uuid/") + getSecretValueInput = &awssm.GetSecretValueInput{ + SecretId: &ref.Key, + VersionId: &versionID, + } + } else { + getSecretValueInput = &awssm.GetSecretValueInput{ + SecretId: &ref.Key, + VersionStage: &ver, + } + } + secretOut, err = sm.client.GetSecretValue(getSecretValueInput) + var nf *awssm.ResourceNotFoundException + if errors.As(err, &nf) { + return nil, esv1beta1.NoSecretErr + } + if err != nil { + return nil, err } } - secretOut, err := sm.client.GetSecretValue(getSecretValueInput) - var nf *awssm.ResourceNotFoundException - if errors.As(err, &nf) { - return nil, esv1beta1.NoSecretErr + sm.cache[cacheKey] = secretOut + + return secretOut, nil +} + +func TagsToJSONString(tags []*awssm.Tag) (string, error) { + tagMap := make(map[string]string, len(tags)) + for _, tag := range tags { + tagMap[*tag.Key] = *tag.Value } + + byteArr, err := json.Marshal(tagMap) if err != nil { - return nil, err + return "", err } - sm.cache[cacheKey] = secretOut - return secretOut, nil + return string(byteArr), nil } func (sm *SecretsManager) DeleteSecret(ctx context.Context, remoteRef esv1beta1.PushRemoteRef) error { diff --git a/pkg/provider/aws/secretsmanager/secretsmanager_test.go b/pkg/provider/aws/secretsmanager/secretsmanager_test.go index f4464f967e3..e326e537bd3 100644 --- a/pkg/provider/aws/secretsmanager/secretsmanager_test.go +++ b/pkg/provider/aws/secretsmanager/secretsmanager_test.go @@ -46,6 +46,12 @@ type secretsManagerTestCase struct { } const unexpectedErrorString = "[%d] unexpected error: %s, expected: '%s'" +const ( + tagname1 = "tagname1" + tagvalue1 = "tagvalue1" + tagname2 = "tagname2" + tagvalue2 = "tagvalue2" +) func makeValidSecretsManagerTestCase() *secretsManagerTestCase { smtc := secretsManagerTestCase{ @@ -175,6 +181,41 @@ func TestSecretsManagerGetSecret(t *testing.T) { smtc.expectedSecret = "myvalue" } + fetchMetadata := func(smtc *secretsManagerTestCase) { + smtc.remoteRef.MetadataPolicy = esv1beta1.ExternalSecretMetadataPolicyFetch + describeSecretOutput := &awssm.DescribeSecretOutput{ + Tags: getTagSlice(), + } + smtc.fakeClient.DescribeSecretWithContextFn = fakesm.NewDescribeSecretWithContextFn(describeSecretOutput, nil) + jsonTags, _ := TagsToJSONString(getTagSlice()) + smtc.apiOutput.SecretString = &jsonTags + smtc.expectedSecret = jsonTags + } + + fetchMetadataProperty := func(smtc *secretsManagerTestCase) { + smtc.remoteRef.MetadataPolicy = esv1beta1.ExternalSecretMetadataPolicyFetch + describeSecretOutput := &awssm.DescribeSecretOutput{ + Tags: getTagSlice(), + } + smtc.fakeClient.DescribeSecretWithContextFn = fakesm.NewDescribeSecretWithContextFn(describeSecretOutput, nil) + smtc.remoteRef.Property = tagname2 + jsonTags, _ := TagsToJSONString(getTagSlice()) + smtc.apiOutput.SecretString = &jsonTags + smtc.expectedSecret = tagvalue2 + } + + failMetadataWrongProperty := func(smtc *secretsManagerTestCase) { + smtc.remoteRef.MetadataPolicy = esv1beta1.ExternalSecretMetadataPolicyFetch + describeSecretOutput := &awssm.DescribeSecretOutput{ + Tags: getTagSlice(), + } + smtc.fakeClient.DescribeSecretWithContextFn = fakesm.NewDescribeSecretWithContextFn(describeSecretOutput, nil) + smtc.remoteRef.Property = "fail" + jsonTags, _ := TagsToJSONString(getTagSlice()) + smtc.apiOutput.SecretString = &jsonTags + smtc.expectError = "key fail does not exist in secret /baz" + } + successCases := []*secretsManagerTestCase{ makeValidSecretsManagerTestCase(), makeValidSecretsManagerTestCaseCustom(setSecretString), @@ -188,6 +229,9 @@ func TestSecretsManagerGetSecret(t *testing.T) { makeValidSecretsManagerTestCaseCustom(setCustomVersionStage), makeValidSecretsManagerTestCaseCustom(setCustomVersionID), makeValidSecretsManagerTestCaseCustom(setAPIErr), + makeValidSecretsManagerTestCaseCustom(fetchMetadata), + makeValidSecretsManagerTestCaseCustom(fetchMetadataProperty), + makeValidSecretsManagerTestCaseCustom(failMetadataWrongProperty), } for k, v := range successCases { @@ -700,3 +744,21 @@ func makeValidSecretStore() *esv1beta1.SecretStore { }, } } + +func getTagSlice() []*awssm.Tag { + tagKey1 := tagname1 + tagValue1 := tagvalue1 + tagKey2 := tagname2 + tagValue2 := tagvalue2 + + return []*awssm.Tag{ + { + Key: &tagKey1, + Value: &tagValue1, + }, + { + Key: &tagKey2, + Value: &tagValue2, + }, + } +} From 6ecd826a32b44e2f3e7eda6121fdbf80585b0265 Mon Sep 17 00:00:00 2001 From: Ehud Yonasi Date: Tue, 21 Feb 2023 20:17:22 +0200 Subject: [PATCH 28/62] Fix for the PushSecret example docs (#2034) Co-authored-by: eyonasi From 0ed699537a88cd8d65293fd2a81499686c04d147 Mon Sep 17 00:00:00 2001 From: bvdboom Date: Wed, 22 Feb 2023 17:13:13 +0100 Subject: [PATCH 29/62] Update azure-key-vault.md (#2039) Removing redundant pipe Signed-off-by: bvdboom --- docs/provider/azure-key-vault.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/provider/azure-key-vault.md b/docs/provider/azure-key-vault.md index 34635cc68de..9ba15ffb7dc 100644 --- a/docs/provider/azure-key-vault.md +++ b/docs/provider/azure-key-vault.md @@ -123,7 +123,7 @@ You can manage keys/secrets/certificates saved inside the keyvault , by setting The operator will fetch the Azure Key vault secret and inject it as a `Kind=Secret`. Then the Kubernetes secret can be fetched by issuing: ```sh -kubectl get secret secret-to-be-created -n | -o jsonpath='{.data.dev-secret-test}' | base64 -d +kubectl get secret secret-to-be-created -n -o jsonpath='{.data.dev-secret-test}' | base64 -d ``` To select all secrets inside the key vault or all tags inside a secret, you can use the `dataFrom` directive: From 13f26e6e24431132ac31742908bdcce6f2c417d0 Mon Sep 17 00:00:00 2001 From: bvdboom Date: Thu, 23 Feb 2023 14:08:39 +0100 Subject: [PATCH 30/62] :book: fix typo (#2042) Signed-off-by: bvdboom Co-authored-by: Bernard --- docs/api/controller-options.md | 4 ++-- docs/api/spec.md | 2 +- docs/contributing/process.md | 2 +- docs/examples/jenkins-kubernetes-credentials.md | 2 +- docs/guides/multi-tenancy.md | 2 +- docs/guides/templating.md | 6 +++--- docs/provider/azure-key-vault.md | 4 ++-- docs/provider/google-secrets-manager.md | 4 ++-- docs/spec.md | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/api/controller-options.md b/docs/api/controller-options.md index 78df1ca3c12..b390b57714d 100644 --- a/docs/api/controller-options.md +++ b/docs/api/controller-options.md @@ -11,7 +11,7 @@ The external-secrets binary includes three components: `core controller`, `certc The core controller is invoked without a subcommand and can be configured with the following flags: -| Name | Type | Default | Descripton | +| Name | Type | Default | Description | | --------------------------------------------- | -------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `--client-burst` | int | uses rest client default (10) | Maximum Burst allowed to be passed to rest.Client | | `--client-qps` | float32 | uses rest client default (5) | QPS configuration to be passed to rest.Client | @@ -47,7 +47,7 @@ The core controller is invoked without a subcommand and can be configured with t ## Webhook Flags -| Name | Type | Default | Descripton | +| Name | Type | Default | Description | | ---------------------- | -------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `--cert-dir` | string | /tmp/k8s-webhook-server/serving-certs | path to check for certs | | `--check-interval` | duration | 5m0s | certificate check interval | diff --git a/docs/api/spec.md b/docs/api/spec.md index 90a595681dc..80081a305de 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -5185,7 +5185,7 @@ External Secrets meta/v1.SecretKeySelector

Error indicates that there is a misconfiguration.

0

-

Ready indicates that the client is confgured correctly +

Ready indicates that the client is configured correctly and can be used.

1

diff --git a/docs/contributing/process.md b/docs/contributing/process.md index bf156b6aaf8..ef162c06439 100644 --- a/docs/contributing/process.md +++ b/docs/contributing/process.md @@ -58,7 +58,7 @@ make test.e2e GINKGO_LABELS='gcp&&!managed' #### Managed Kubernetes e2e tests -There's another suite of e2e tests that integrate with managed Kuberentes offerings. +There's another suite of e2e tests that integrate with managed Kubernetes offerings. They create real infrastructure at a cloud provider and deploy the controller into that environment. This is necessary to test the authentication integration diff --git a/docs/examples/jenkins-kubernetes-credentials.md b/docs/examples/jenkins-kubernetes-credentials.md index 0f7193b1ee1..3dbd6d20ff3 100644 --- a/docs/examples/jenkins-kubernetes-credentials.md +++ b/docs/examples/jenkins-kubernetes-credentials.md @@ -1,6 +1,6 @@ # Getting started -Jenkins is one of the most popular automation servers for continous integration, automation, scheduling jobs and for generic pipelining. It has an extensive set of plugins that extend or provide additional functionality including the [kubernetes credentials plugin](https://github.com/jenkinsci/kubernetes-credentials-provider-plugin). This plugin takes kubernetes secrets and creates Jenkins credentials from them removing the need for manual entry of secrets, local storage and manual secret rotation. +Jenkins is one of the most popular automation servers for continuous integration, automation, scheduling jobs and for generic pipelining. It has an extensive set of plugins that extend or provide additional functionality including the [kubernetes credentials plugin](https://github.com/jenkinsci/kubernetes-credentials-provider-plugin). This plugin takes kubernetes secrets and creates Jenkins credentials from them removing the need for manual entry of secrets, local storage and manual secret rotation. ## Examples diff --git a/docs/guides/multi-tenancy.md b/docs/guides/multi-tenancy.md index 52ee23b6043..cb2dd1fe97e 100644 --- a/docs/guides/multi-tenancy.md +++ b/docs/guides/multi-tenancy.md @@ -1,5 +1,5 @@ External Secrets Operator provides different modes of operation to fulfill -ogranizational needs. This guide outlines the flexibility of ESO and should give +organizational needs. This guide outlines the flexibility of ESO and should give you a first impression of how you can employ this operator in your organization. For a multi-tenant deployment you should first examine your organizational diff --git a/docs/guides/templating.md b/docs/guides/templating.md index 561bcde8e9d..480b068fd2b 100644 --- a/docs/guides/templating.md +++ b/docs/guides/templating.md @@ -146,9 +146,9 @@ spec: ##### Functions removed/replaced - `base64encode` was renamed to `b64enc`. -- `base64decode` was renamed to `b64dec`. Any errors that occurr during decoding are silenced. -- `fromJSON` was renamed to `fromJson`. Any errors that occurr during unmarshalling are silenced. -- `toJSON` was renamed to `toJson`. Any errors that occurr during marshalling are silenced. +- `base64decode` was renamed to `b64dec`. Any errors that occur during decoding are silenced. +- `fromJSON` was renamed to `fromJson`. Any errors that occur during unmarshalling are silenced. +- `toJSON` was renamed to `toJson`. Any errors that occur during marshalling are silenced. - `pkcs12key` and `pkcs12keyPass` encode the PKCS#8 key directly into PEM format. There is no need to call `pemPrivateKey` anymore. Also, these functions do extract all private keys from the PKCS#12 archive not just the first one. - `pkcs12cert` and `pkcs12certPass` encode the certs directly into PEM format. There is no need to call `pemCertificate` anymore. These functions now **extract all certificates** from the PKCS#12 archive not just the first one. - `toString` implementation was replaced by the `sprig` implementation and should be api-compatible. diff --git a/docs/provider/azure-key-vault.md b/docs/provider/azure-key-vault.md index 9ba15ffb7dc..59e6468d5a7 100644 --- a/docs/provider/azure-key-vault.md +++ b/docs/provider/azure-key-vault.md @@ -40,7 +40,7 @@ A service Principal client and Secret is created and the JSON keyfile is stored A Managed Identity should be created in Azure, and that Identity should have proper rights to the keyvault to be managed by the operator. -If there are multiple Managed Identitites for different keyvaults, the operator should have been assigned all identities via [aad-pod-identity](https://azure.github.io/aad-pod-identity/docs/), then the SecretStore configuration should include the Id of the idenetity to be used via the `identityId` field. +If there are multiple Managed Identities for different keyvaults, the operator should have been assigned all identities via [aad-pod-identity](https://azure.github.io/aad-pod-identity/docs/), then the SecretStore configuration should include the Id of the identity to be used via the `identityId` field. ```yaml {% include 'azkv-secret-store-mi.yaml' %} @@ -94,7 +94,7 @@ Be sure the `azurekv` provider is listed in the `Kind=SecretStore` ``` **NOTE:** In case of a `ClusterSecretStore`, Be sure to provide `namespace` in `clientId` and `clientSecret` with the namespaces where the secrets reside. -Or in case of Managed Idenetity authentication: +Or in case of Managed Identity authentication: ```yaml {% include 'azkv-secret-store-mi.yaml' %} diff --git a/docs/provider/google-secrets-manager.md b/docs/provider/google-secrets-manager.md index e0b7f640b94..edee225308a 100644 --- a/docs/provider/google-secrets-manager.md +++ b/docs/provider/google-secrets-manager.md @@ -19,7 +19,7 @@ _Note: If you have installed ESO, a serviceaccount has already been created. You - `PROJECT_ID`: Your project ID (not your Project number nor your Project name) - `K8S_NAMESPACE`: For us following these steps here it will be `es`, but this will be the namespace where you deployed the external-secrets operator - `KSA_NAME`: external-secrets (if you are not creating a new one to attach to the deployment) -- `GSA_NAME`: external-secrets for simplicity, or something else if you have to follow different naming convetions for cloud resources +- `GSA_NAME`: external-secrets for simplicity, or something else if you have to follow different naming conventions for cloud resources - `ROLE_NAME`: should be `roles/secretmanager.secretAccessor` - so you make the pod only be able to access secrets on Secret Manager #### Using Service Accounts directly @@ -80,7 +80,7 @@ You just need to set the `projectID`, all other fields can be omitted. ### GCP Service Account authentication You can use [GCP Service Account](https://cloud.google.com/iam/docs/service-accounts) to authenticate with GCP. These are static, long-lived credentials. A GCP Service Account is a JSON file that needs to be stored in a `Kind=Secret`. ESO will use that Secret to authenticate with GCP. See here how you [manage GCP Service Accounts](https://cloud.google.com/iam/docs/creating-managing-service-accounts). -After creating a GCP Service acount go to `IAM & Admin` web UI, click `ADD ANOTHER ROLE` button, add `Secret Manager Secret Accessor` role to this service account. +After creating a GCP Service account go to `IAM & Admin` web UI, click `ADD ANOTHER ROLE` button, add `Secret Manager Secret Accessor` role to this service account. The `Secret Manager Secret Accessor` role is required to access secrets. ```yaml diff --git a/docs/spec.md b/docs/spec.md index 8abad4f8883..63141bfe83d 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -4935,7 +4935,7 @@ github.com/external-secrets/external-secrets/apis/meta/v1.SecretKeySelector

Error indicates that there is a misconfiguration.

0

-

Ready indicates that the client is confgured correctly +

Ready indicates that the client is configured correctly and can be used.

1

From 4e4992f0e2fa94ef0b5599a9cb58b768972345f1 Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Mon, 27 Feb 2023 13:15:11 +0100 Subject: [PATCH 31/62] :broom: bump dependencies (#2061) Signed-off-by: Moritz Johner --- apis/externalsecrets/v1beta1/provider.go | 2 +- e2e/go.mod | 18 ++--- e2e/go.sum | 36 +++++----- go.mod | 26 ++++---- go.sum | 85 ++++++++---------------- 5 files changed, 68 insertions(+), 99 deletions(-) diff --git a/apis/externalsecrets/v1beta1/provider.go b/apis/externalsecrets/v1beta1/provider.go index 28164342124..432960d2c16 100644 --- a/apis/externalsecrets/v1beta1/provider.go +++ b/apis/externalsecrets/v1beta1/provider.go @@ -21,7 +21,7 @@ import ( ) const ( - // Ready indicates that the client is confgured correctly + // Ready indicates that the client is configured correctly // and can be used. ValidationResultReady ValidationResult = iota diff --git a/e2e/go.mod b/e2e/go.mod index 81c75798b60..9806b557aa1 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -43,9 +43,9 @@ require ( github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 github.com/akeylesslabs/akeyless-go/v2 v2.20.3 - github.com/aliyun/alibaba-cloud-sdk-go v1.62.174 + github.com/aliyun/alibaba-cloud-sdk-go v1.62.192 github.com/argoproj/argo-cd/v2 v2.4.8 - github.com/aws/aws-sdk-go v1.44.204 + github.com/aws/aws-sdk-go v1.44.209 github.com/external-secrets/external-secrets v0.0.0 github.com/fluxcd/helm-controller/api v0.22.2 github.com/fluxcd/pkg/apis/meta v0.14.2 @@ -53,7 +53,7 @@ require ( github.com/golang-jwt/jwt/v4 v4.5.0 github.com/hashicorp/vault/api v1.9.0 github.com/onsi/ginkgo/v2 v2.8.3 - github.com/onsi/gomega v1.27.0 + github.com/onsi/gomega v1.27.1 github.com/oracle/oci-go-sdk/v56 v56.1.0 github.com/xanzy/go-gitlab v0.80.2 golang.org/x/oauth2 v0.5.0 @@ -62,7 +62,7 @@ require ( k8s.io/apiextensions-apiserver v0.26.1 k8s.io/apimachinery v0.26.1 k8s.io/client-go v1.5.2 - k8s.io/utils v0.0.0-20230209194617-a36077c30491 + k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 sigs.k8s.io/controller-runtime v0.14.4 software.sslmate.com/src/go-pkcs12 v0.2.0 ) @@ -129,7 +129,7 @@ require ( github.com/google/go-github/v41 v41.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect + github.com/google/pprof v0.0.0-20230222194610-99052d3372e7 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect @@ -175,7 +175,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.39.0 // indirect + github.com/prometheus/common v0.40.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/robfig/cron v1.2.0 // indirect github.com/russross/blackfriday v1.5.2 // indirect @@ -197,7 +197,7 @@ require ( go.opencensus.io v0.24.0 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect golang.org/x/crypto v0.6.0 // indirect - golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb // indirect + golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect golang.org/x/net v0.7.0 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.5.0 // indirect @@ -207,7 +207,7 @@ require ( golang.org/x/tools v0.6.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44 // indirect + google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 // indirect google.golang.org/grpc v1.53.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect @@ -223,7 +223,7 @@ require ( k8s.io/component-helpers v0.24.2 // indirect k8s.io/klog/v2 v2.90.0 // indirect k8s.io/kube-aggregator v0.24.2 // indirect - k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d // indirect + k8s.io/kube-openapi v0.0.0-20230224204730-66828de6f33b // indirect k8s.io/kubectl v0.24.2 // indirect k8s.io/kubernetes v1.24.2 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/e2e/go.sum b/e2e/go.sum index 1960e940b7e..24fc66ae865 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -125,8 +125,8 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI= github.com/alicebob/miniredis/v2 v2.14.2 h1:VeoqKUAsJfT2af61nDE7qhBzqn3J6xjnt9MFAbdrEtg= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.174 h1:K5561f5qv64GmtQuY0OtkY0H2x1bTXBeYwwWFPzc4D8= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.174/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.192 h1:tsF4NZgpWu/2vxTKJUTpg24UxLlkzmox3ezOqPZGcr8= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.192/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -154,8 +154,8 @@ github.com/aws/aws-sdk-go v1.33.16/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZve github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= github.com/aws/aws-sdk-go v1.38.49/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.44.204 h1:7/tPUXfNOHB390A63t6fJIwmlwVQAkAwcbzKsU2/6OQ= -github.com/aws/aws-sdk-go v1.44.204/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.209 h1:wZuiaA4eaqYZmoZXqGgNHqVD7y7kUGFvACDGBgowTps= +github.com/aws/aws-sdk-go v1.44.209/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -484,8 +484,8 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= +github.com/google/pprof v0.0.0-20230222194610-99052d3372e7 h1:pNFnpaSXfibgW7aUbk9pwLmI7LNwh/iR46x/YwN/lNg= +github.com/google/pprof v0.0.0-20230222194610-99052d3372e7/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -749,8 +749,8 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= -github.com/onsi/gomega v1.27.0 h1:QLidEla4bXUuZVFa4KX6JHCsuGgbi85LC/pCHrt/O08= -github.com/onsi/gomega v1.27.0/go.mod h1:i189pavgK95OSIipFBa74gC2V4qrQuvjuyGEr3GmbXA= +github.com/onsi/gomega v1.27.1 h1:rfztXRbg6nv/5f+Raen9RcGoSecHIFgBBLQK3Wdj754= +github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfadcIAw= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -821,8 +821,8 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= -github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= +github.com/prometheus/common v0.40.0 h1:Afz7EVRqGg2Mqqf4JuF9vdvp1pi220m55Pi9T2JnO4Q= +github.com/prometheus/common v0.40.0/go.mod h1:L65ZJPSmfn/UBWLQIHV7dBrKFidB/wPlF1y5TlSt9OE= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -1074,8 +1074,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20210220032938-85be41e4509f/go.mod h1:I6l2HNBLBZEcrOoCpyKLdY2lHoRZ8lI4x60KMCQDft4= golang.org/x/exp v0.0.0-20210901193431-a062eea981d2/go.mod h1:a3o/VtDNHN+dCVLEpzjjUHOzR+Ln3DHX056ZPzoZGGA= -golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w= -golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI= +golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1486,8 +1486,8 @@ google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44 h1:EfLuoKW5WfkgVdDy7dTK8qSbH37AX5mj/MFh+bGPz14= -google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 h1:znp6mq/drrY+6khTAlJUDNFFcDGV2ENLYKpMq8SyCds= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1629,8 +1629,8 @@ k8s.io/kube-aggregator v0.24.2/go.mod h1:Ju2jNDixn+vqeeKEBfjfpc204bO1pbdXX0N9knC k8s.io/kube-controller-manager v0.24.2/go.mod h1:KDE0yqiEvxYiO0WRpPA4rVx8AcK1vsWydUF37AJ9lTI= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d h1:oFDpQ7FfzinCtrFOl4izwOWsdTprlS2A9IXBENMW0UA= -k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= +k8s.io/kube-openapi v0.0.0-20230224204730-66828de6f33b h1:4dkmFEDQj0ZBLKCxJ0R+qzhvZmEvRdRaaZAE06tR/Lg= +k8s.io/kube-openapi v0.0.0-20230224204730-66828de6f33b/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY= k8s.io/kube-proxy v0.24.2/go.mod h1:bozS2ufl/Ns6s40Ue34eV7rqyLVygi5usSmCgW7rFU8= k8s.io/kube-scheduler v0.24.2/go.mod h1:DRa+aeXKSYUUOHHIc/9EcaO9+FW5FydaOfPSvaSW5Ko= k8s.io/kubectl v0.24.2 h1:+RfQVhth8akUmIc2Ge8krMl/pt66V7210ka3RE/p0J4= @@ -1647,8 +1647,8 @@ k8s.io/system-validators v1.7.0/go.mod h1:gP1Ky+R9wtrSiFbrpEPwWMeYz9yqyy1S/KOh0V k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= -k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk= +k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= diff --git a/go.mod b/go.mod index e042f88360d..1e14ffb7066 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/Azure/go-autorest/autorest/adal v0.9.22 github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 - github.com/IBM/go-sdk-core/v5 v5.12.1 + github.com/IBM/go-sdk-core/v5 v5.13.0 github.com/IBM/secrets-manager-go-sdk v1.0.49 github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/sprig/v3 v3.2.3 @@ -48,8 +48,8 @@ require ( github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 github.com/akeylesslabs/akeyless-go/v2 v2.20.3 - github.com/aliyun/alibaba-cloud-sdk-go v1.62.174 - github.com/aws/aws-sdk-go v1.44.204 + github.com/aliyun/alibaba-cloud-sdk-go v1.62.192 + github.com/aws/aws-sdk-go v1.44.209 github.com/go-logr/logr v1.2.3 github.com/go-test/deep v1.0.4 // indirect github.com/google/go-cmp v0.5.9 @@ -62,7 +62,7 @@ require ( github.com/huandu/xstrings v1.4.0 // indirect github.com/lestrrat-go/jwx v1.2.25 github.com/onsi/ginkgo/v2 v2.8.3 - github.com/onsi/gomega v1.27.0 + github.com/onsi/gomega v1.27.1 github.com/oracle/oci-go-sdk/v56 v56.1.0 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 @@ -70,14 +70,14 @@ require ( github.com/stretchr/testify v1.8.1 github.com/tidwall/gjson v1.14.4 github.com/xanzy/go-gitlab v0.80.2 - github.com/yandex-cloud/go-genproto v0.0.0-20230213085250-850b3568e0c5 + github.com/yandex-cloud/go-genproto v0.0.0-20230220085534-5bd8ccb5865a github.com/yandex-cloud/go-sdk v0.0.0-20230213085834-eedd655a7e14 github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a go.uber.org/zap v1.24.0 golang.org/x/crypto v0.6.0 golang.org/x/oauth2 v0.5.0 google.golang.org/api v0.110.0 - google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44 // indirect + google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 // indirect google.golang.org/grpc v1.53.0 gopkg.in/yaml.v3 v3.0.1 grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 @@ -85,7 +85,7 @@ require ( k8s.io/apiextensions-apiserver v0.26.1 k8s.io/apimachinery v0.26.1 k8s.io/client-go v1.5.2 - k8s.io/utils v0.0.0-20230209194617-a36077c30491 + k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 sigs.k8s.io/controller-runtime v0.14.4 sigs.k8s.io/controller-tools v0.11.3 ) @@ -105,6 +105,7 @@ require ( require ( cloud.google.com/go/compute/metadata v0.2.3 // indirect + github.com/go-playground/validator/v10 v10.11.2 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect ) @@ -142,7 +143,7 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect - github.com/gobuffalo/flect v1.0.0 // indirect + github.com/gobuffalo/flect v1.0.2 // indirect github.com/goccy/go-json v0.10.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect @@ -151,7 +152,7 @@ require ( github.com/google/gnostic v0.6.9 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect + github.com/google/pprof v0.0.0-20230222194610-99052d3372e7 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -192,7 +193,7 @@ require ( github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/common v0.39.0 // indirect + github.com/prometheus/common v0.40.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect @@ -207,7 +208,7 @@ require ( go.opencensus.io v0.24.0 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb + golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 golang.org/x/mod v0.8.0 // indirect golang.org/x/net v0.7.0 // indirect golang.org/x/sys v0.5.0 // indirect @@ -218,7 +219,6 @@ require ( gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect - gopkg.in/go-playground/validator.v9 v9.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect @@ -227,7 +227,7 @@ require ( k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9 // indirect k8s.io/klog v1.0.0 // indirect k8s.io/klog/v2 v2.90.0 // indirect - k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d // indirect + k8s.io/kube-openapi v0.0.0-20230224204730-66828de6f33b // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/go.sum b/go.sum index fe9d5795998..fb75e3e261d 100644 --- a/go.sum +++ b/go.sum @@ -88,8 +88,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= -github.com/IBM/go-sdk-core/v5 v5.12.1 h1:9hb9oosBma4+N05xmKmtAW13T1nfADMVYRE7fu06lZ0= -github.com/IBM/go-sdk-core/v5 v5.12.1/go.mod h1:WZPFasUzsKab/2mzt29xPcfruSk5js2ywAPwW4VJjdI= +github.com/IBM/go-sdk-core/v5 v5.13.0 h1:foXLa2LfTSr3kgldpizaSDXH3gS/HB3YKj1BK8ywrE4= +github.com/IBM/go-sdk-core/v5 v5.13.0/go.mod h1:pVkN7IGmsSdmR1ZCU4E/cLcCclqRKMYgg7ya+O2Mk6g= github.com/IBM/secrets-manager-go-sdk v1.0.49 h1:wRxyjFpSoZz6brj55JSMk6Sb38dLrQYnsEKcdYibflo= github.com/IBM/secrets-manager-go-sdk v1.0.49/go.mod h1:QyDSznC6gJEXIGaj+JPxoEVtyXfkaxzId87mxcEb+vM= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -112,16 +112,16 @@ github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 h1:vTckjyBhHOBiOWSC/oaEU2Oo4 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4/go.mod h1:As/RomC2w/fa3y+yHRlVHPmkbP+zrKBFRow41y5dk+E= github.com/akeylesslabs/akeyless-go/v2 v2.20.3 h1:NIRMynmpQbfgQyRLf5DMQC8p5iLgaUu1MXBB4ijLCxM= github.com/akeylesslabs/akeyless-go/v2 v2.20.3/go.mod h1:uOdXD49NCCe4rexeSc2aBU5Qv4KZgJE6YlbtYalvb+I= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.174 h1:K5561f5qv64GmtQuY0OtkY0H2x1bTXBeYwwWFPzc4D8= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.174/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.192 h1:tsF4NZgpWu/2vxTKJUTpg24UxLlkzmox3ezOqPZGcr8= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.192/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.44.204 h1:7/tPUXfNOHB390A63t6fJIwmlwVQAkAwcbzKsU2/6OQ= -github.com/aws/aws-sdk-go v1.44.204/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.209 h1:wZuiaA4eaqYZmoZXqGgNHqVD7y7kUGFvACDGBgowTps= +github.com/aws/aws-sdk-go v1.44.209/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -182,8 +182,6 @@ github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8Wlg github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= @@ -210,18 +208,19 @@ github.com/go-openapi/strfmt v0.21.3 h1:xwhj5X6CjXEZZHMWy1zKJxvW9AfHC9pkyUjLvHtK github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU= +github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/gobuffalo/flect v1.0.0 h1:eBFmskjXZgAOagiTXJH25Nt5sdFwNRcb8DKZsIsAUQI= -github.com/gobuffalo/flect v1.0.0/go.mod h1:l9V6xSb4BlXwsxEMj3FVEub2nkdQjWhPvD8XTTlHPQc= +github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA= +github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= @@ -305,9 +304,8 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= +github.com/google/pprof v0.0.0-20230222194610-99052d3372e7 h1:pNFnpaSXfibgW7aUbk9pwLmI7LNwh/iR46x/YwN/lNg= +github.com/google/pprof v0.0.0-20230222194610-99052d3372e7/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -334,7 +332,6 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0= github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= @@ -362,7 +359,6 @@ github.com/hashicorp/vault/api/auth/kubernetes v0.4.0 h1:f6OIOF9012JIdqYvOeeewxh github.com/hashicorp/vault/api/auth/kubernetes v0.4.0/go.mod h1:tMewM2hPyFNKP1EXdWbc0dUHHoS5V/0qS04BEaxuy78= github.com/hashicorp/vault/api/auth/ldap v0.4.0 h1:/P2HCNmcDY6s22JBXxVhr9noaFqPEQS2qwSnWIYezkc= github.com/hashicorp/vault/api/auth/ldap v0.4.0/go.mod h1:RJawcFnbfk3zyB9lDbFeGT5YkaAoWTpACEApFt5/TU0= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= @@ -468,25 +464,14 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.8.3 h1:RpbK1G8nWPNaCVFBWsOGnEQQGgASi6b8fxcWBvDYjxQ= github.com/onsi/ginkgo/v2 v2.8.3/go.mod h1:6OaUA8BCi0aZfmzYT/q9AacwTzDpNbxILUT+TlBq6MY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.18.0/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/onsi/gomega v1.27.0 h1:QLidEla4bXUuZVFa4KX6JHCsuGgbi85LC/pCHrt/O08= -github.com/onsi/gomega v1.27.0/go.mod h1:i189pavgK95OSIipFBa74gC2V4qrQuvjuyGEr3GmbXA= +github.com/onsi/gomega v1.27.1 h1:rfztXRbg6nv/5f+Raen9RcGoSecHIFgBBLQK3Wdj754= +github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfadcIAw= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= @@ -505,8 +490,8 @@ github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQg github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= -github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= +github.com/prometheus/common v0.40.0 h1:Afz7EVRqGg2Mqqf4JuF9vdvp1pi220m55Pi9T2JnO4Q= +github.com/prometheus/common v0.40.0/go.mod h1:L65ZJPSmfn/UBWLQIHV7dBrKFidB/wPlF1y5TlSt9OE= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -573,8 +558,9 @@ github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgk github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/yandex-cloud/go-genproto v0.0.0-20230213085250-850b3568e0c5 h1:dFinCaaTET9YTJjq1jC/V1AEFtya/dzuTO8fpB7jrAY= github.com/yandex-cloud/go-genproto v0.0.0-20230213085250-850b3568e0c5/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= +github.com/yandex-cloud/go-genproto v0.0.0-20230220085534-5bd8ccb5865a h1:B0DLopiKFTX1y6rTHPRALhad4TP3dSAW0aTMTb5qSoU= +github.com/yandex-cloud/go-genproto v0.0.0-20230220085534-5bd8ccb5865a/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= github.com/yandex-cloud/go-sdk v0.0.0-20230213085834-eedd655a7e14 h1:2yNVc+wIhp8SwyXdmbxGl7vT47oJWYxYxmRzReUelZM= github.com/yandex-cloud/go-sdk v0.0.0-20230213085834-eedd655a7e14/go.mod h1:iICjK1Tf7LbahA6tJJ4akCHKnTjeGP+ceQKsjtWOiyo= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= @@ -638,8 +624,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w= -golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI= +golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -669,7 +655,6 @@ golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -690,7 +675,6 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -703,7 +687,6 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -742,7 +725,6 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -752,11 +734,8 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -778,7 +757,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -792,7 +770,6 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -878,7 +855,6 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= @@ -970,8 +946,8 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44 h1:EfLuoKW5WfkgVdDy7dTK8qSbH37AX5mj/MFh+bGPz14= -google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 h1:znp6mq/drrY+6khTAlJUDNFFcDGV2ENLYKpMq8SyCds= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1018,11 +994,6 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M= -gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -1032,10 +1003,8 @@ gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76 gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -1075,10 +1044,10 @@ k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.90.0 h1:VkTxIV/FjRXn1fgNNcKGM8cfmL1Z33ZjXRTVxKCoF5M= k8s.io/klog/v2 v2.90.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d h1:oFDpQ7FfzinCtrFOl4izwOWsdTprlS2A9IXBENMW0UA= -k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= -k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= -k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-openapi v0.0.0-20230224204730-66828de6f33b h1:4dkmFEDQj0ZBLKCxJ0R+qzhvZmEvRdRaaZAE06tR/Lg= +k8s.io/kube-openapi v0.0.0-20230224204730-66828de6f33b/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY= +k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk= +k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= From b0276e3029667d88b16e5a7c20b93d18d73dcf67 Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Mon, 27 Feb 2023 22:51:59 +0100 Subject: [PATCH 32/62] feat: exempt kind/feature issues from going stale (#2067) Signed-off-by: Moritz Johner --- .github/workflows/stale.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 1c09b6cfdec..599db4aeb90 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -13,5 +13,6 @@ jobs: stale-issue-message: 'This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 30 days.' stale-pr-message: 'This pr is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 30 days.' close-issue-message: 'This issue was closed because it has been stalled for 30 days with no activity.' + exempt-issue-labels: kind/feature days-before-stale: 90 days-before-close: 30 From 6b576fadf1669312e5b529c1457209d4f2d23186 Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Mon, 27 Feb 2023 22:56:36 +0100 Subject: [PATCH 33/62] feat: add provider metrics (#2024) * feat: add provider metrics This adds a counter metric `provider_api_calls_count` that observes the results of upstream secret provider api calls. (1) Observability It allows an user to break down issues by provider and api call by observing the status=error|success label. More details around the error can be found in the logs. (2) Cost Management Some providers charge by API calls issued. By providing observability for the number of calls issued helps users to understand the impact of deploying ESO and fine-tuning `spec.refreshInterval`. (3) Rate Limiting Some providers implement rate-limiting for their services. Having metrics for success/failure count helps to understand how many requests are issued by a given ESO deployment per cluster. Signed-off-by: Moritz Johner * fix: add service monitor for cert-controller and add SLIs Signed-off-by: Moritz Johner --------- Signed-off-by: Moritz Johner --- .../external-secrets/templates/_helpers.tpl | 10 + .../templates/servicemonitor.yaml | 97 ++ docs/api/metrics.md | 65 ++ docs/pictures/eso-dashboard-1.png | Bin 0 -> 93964 bytes docs/pictures/eso-dashboard-2.png | Bin 0 -> 120286 bytes docs/snippets/dashboard.json | 984 ++++++++++++++++++ .../aws/parameterstore/parameterstore.go | 12 +- .../aws/secretsmanager/secretsmanager.go | 11 + pkg/provider/azure/keyvault/keyvault.go | 17 + pkg/provider/gcp/secretmanager/client.go | 21 +- .../gcp/secretmanager/workload_identity.go | 4 + pkg/provider/gitlab/gitlab.go | 9 + pkg/provider/ibm/provider.go | 14 + pkg/provider/kubernetes/client.go | 4 + pkg/provider/kubernetes/validate.go | 2 + pkg/provider/metrics/metrics.go | 116 +++ pkg/provider/vault/vault.go | 15 + pkg/provider/webhook/webhook.go | 2 + 18 files changed, 1377 insertions(+), 6 deletions(-) create mode 100644 docs/pictures/eso-dashboard-1.png create mode 100644 docs/pictures/eso-dashboard-2.png create mode 100644 docs/snippets/dashboard.json create mode 100644 pkg/provider/metrics/metrics.go diff --git a/deploy/charts/external-secrets/templates/_helpers.tpl b/deploy/charts/external-secrets/templates/_helpers.tpl index 48c9ed979f4..10ccbc488c6 100644 --- a/deploy/charts/external-secrets/templates/_helpers.tpl +++ b/deploy/charts/external-secrets/templates/_helpers.tpl @@ -51,6 +51,11 @@ app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} +{{- define "external-secrets-webhook-metrics.labels" -}} +{{ include "external-secrets-webhook.selectorLabels" . }} +app.kubernetes.io/metrics: "webhook" +{{- end }} + {{- define "external-secrets-cert-controller.labels" -}} helm.sh/chart: {{ include "external-secrets.chart" . }} {{ include "external-secrets-cert-controller.selectorLabels" . }} @@ -60,6 +65,11 @@ app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} +{{- define "external-secrets-cert-controller-metrics.labels" -}} +{{ include "external-secrets-cert-controller.selectorLabels" . }} +app.kubernetes.io/metrics: "cert-controller" +{{- end }} + {{/* Selector labels */}} diff --git a/deploy/charts/external-secrets/templates/servicemonitor.yaml b/deploy/charts/external-secrets/templates/servicemonitor.yaml index b48993a93f7..6b09df5a9d0 100644 --- a/deploy/charts/external-secrets/templates/servicemonitor.yaml +++ b/deploy/charts/external-secrets/templates/servicemonitor.yaml @@ -45,4 +45,101 @@ spec: relabelings: {{- toYaml . | nindent 6 }} {{- end }} +--- +{{- if .Values.webhook.create }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook-metrics + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets-webhook-metrics.labels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - port: 8080 + protocol: TCP + name: metrics + selector: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 4 }} +--- +apiVersion: "monitoring.coreos.com/v1" +kind: ServiceMonitor +metadata: + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} +{{- if .Values.serviceMonitor.additionalLabels }} +{{ toYaml .Values.serviceMonitor.additionalLabels | indent 4 }} +{{- end }} + name: {{ include "external-secrets.fullname" . }}-webhook-metrics + namespace: {{ .Release.Namespace | quote }} +spec: + selector: + matchLabels: + {{- include "external-secrets-webhook-metrics.labels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace | quote }} + endpoints: + - port: metrics + interval: {{ .Values.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + honorLabels: {{ .Values.serviceMonitor.honorLabels }} + {{- with .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} +{{- if .Values.certController.create }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets-cert-controller-metrics.labels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - port: 8080 + protocol: TCP + name: metrics + selector: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 4 }} +--- +apiVersion: "monitoring.coreos.com/v1" +kind: ServiceMonitor +metadata: + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} +{{- if .Values.serviceMonitor.additionalLabels }} +{{ toYaml .Values.serviceMonitor.additionalLabels | indent 4 }} +{{- end }} + name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics + namespace: {{ .Release.Namespace | quote }} +spec: + selector: + matchLabels: + {{- include "external-secrets-cert-controller-metrics.labels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace | quote }} + endpoints: + - port: metrics + interval: {{ .Values.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + honorLabels: {{ .Values.serviceMonitor.honorLabels }} + {{- with .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} {{- end }} diff --git a/docs/api/metrics.md b/docs/api/metrics.md index 862587d69a5..8330fc19f26 100644 --- a/docs/api/metrics.md +++ b/docs/api/metrics.md @@ -15,6 +15,7 @@ The Operator has the metrics inherited from Kubebuilder plus some custom metrics | Name | Type | Description | | ---------------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `externalsecret_provider_api_calls_count` | Counter | Number of API calls made to an upstream secret provider API. The metric provides a `provider`, `call` and `status` labels. | | `externalsecret_sync_calls_total` | Counter | Total number of the External Secret sync calls | | `externalsecret_sync_calls_error` | Counter | Total number of the External Secret sync errors | | `externalsecret_status_condition` | Gauge | The status condition of a specific External Secret | @@ -25,3 +26,67 @@ The Operator has the metrics inherited from Kubebuilder plus some custom metrics | `controller_runtime_reconcile_queue_length` | Gauge | Length of reconcile queue per controller | | `controller_runtime_max_concurrent_reconciles` | Gauge | Maximum number of concurrent reconciles per controller | | `controller_runtime_active_workers` | Gauge | Number of currently used workers per controller | + +## Dashboard + +We provide a [Grafana Dashboard](https://raw.githubusercontent.com/external-secrets/external-secrets/main/docs/snippets/dashboard.json) that gives you an overview of External Secrets Operator: + +![ESO Dashboard](../pictures/eso-dashboard-1.png) +![ESO Dashboard](../pictures/eso-dashboard-2.png) + + +## Service Level Indicators and Alerts + +We find the following Service Level Indicators (SLIs) useful when operating ESO. They should give you a good starting point and hints to develop your own Service Level Objectives (SLOs). + +#### Webhook HTTP Status Codes +The webhook HTTP status code indicates that a HTTP Request was answered successfully or not. +If the Webhook pod is not able to serve the requests properly then that failure may cascade down to the controller or any other user of `kube-apiserver`. + +SLI Example: request error percentage. +``` +sum(increase(controller_runtime_webhook_requests_total{service=~"external-secrets.*",code="500"}[1m])) +/ +sum(increase(controller_runtime_webhook_requests_total{service=~"external-secrets.*"}[1m])) +``` + +#### Webhook HTTP Request Latency +If the webhook server is not able to respond in time then that may cause a timeout at the client. +This failure may cascade down to the controller or any other user of `kube-apiserver`. + +SLI Example: p99 across all webhook requests. +``` +histogram_quantile(0.99, + sum(rate(controller_runtime_webhook_latency_seconds_bucket{service=~"external-secrets.*"}[5m])) by (le) +) +``` + +#### Controller Workqueue Depth +If the workqueue depth is > 0 for a longer period of time then this is an indicator for the controller not being able to reconcile resources in time. I.e. delivery of secret updates is delayed. + +Note: when a controller is restarted, then `queue length = total number of resources`. Make sure to measure the time it takes for the controller to fully reconcile all secrets after a restart. In large clusters this may take a while, make sure to define an acceptable timeframe to fully reconcile all resources. + +``` +sum( + workqueue_depth{service=~"external-secrets.*"} +) by (name) +``` + +#### Controller Reconcile Latency +The controller should be able to reconcile resources within a reasonable timeframe. When latency is high secret delivery may impacted. + +SLI Example: p99 across all controllers. +``` +histogram_quantile(0.99, + sum(rate(controller_runtime_reconcile_time_seconds_bucket{service=~"external-secrets.*"}[5m])) by (le) +) +``` + +#### Controller Reconcile Error +The controller should be able to reconcile resources without errors. When errors occurr secret delivery may be impacted which could cascade down to the secret consuming applications. + +``` +sum(increase( + controller_runtime_reconcile_total{service=~"external-secrets.*",controller=~"$controller"}[1m]) +) by (result) +``` diff --git a/docs/pictures/eso-dashboard-1.png b/docs/pictures/eso-dashboard-1.png new file mode 100644 index 0000000000000000000000000000000000000000..fae5c2797e0daf13390e9cbb350b18a380ffee08 GIT binary patch literal 93964 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

-JWE*Mf#QG9#O`n{_M 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 z z*J2|@E5%#HW^|V#M1QyRtb1MfBF?m-)h{i2m;4mFZ;Y|so(roMba+i{U%Ri@_G-!4 z;F0ePA~dvPZ0vHfF|fc-@;D`;Z7G9jL>v{$;pw`{d9ULB3LYbu1LfLinvIg3&KjxF z=BlgR$@9J9{X8{Xb*pC8xBzK~qaHYY$y0*OQcAV`FR2JnNohjeE2)}!-s5VAy9T1X z+>m&mF`F^FaSf-n4;CwPTlZ`73s^TNG@_lFgfrHQ;5R1vwJ}z^rWJBz-mE7J%64aT z!4jCSvn9+kRg7_6tGY|?&b)Ig`euIxk0Y5HWN$`jK5$x(H}>31k-lkDnkHK?*pVII zVINXYw`HuArD$yBZ?iqWG~U~*U7%y7^)A?4zRs5}x9^H$l?jn$lKpSjV0^KuTlSah z!@?SUlcU*T!gFJBTdHd$(J5QW73O6ftA!jSG9o>WO1vad1*VF%XlCHDHvHaGn7Vr4 zd<#6UoneW*;Psf^dP&Pg!4(s@9Wt{B>k(j#DcZ81i0&1mjp(gne|5>B`Ij~g<`e~1 zQYX`t_YAOcRQ(d=VMD3YXyqZ?Wi&Hy)jTE}rgs)<1&e=T$*% zVQLy3R_PfX{jELBwiA4QU@@6#KyclXT*;0xgMh@AAVre{+n-(W!XZJxP3zXJ&Sx^R+GzV|{d-NBiK3V>-Q%nPm3Y^S_qi^~yGF7?%3F=SbTNqSvB zDtMzW(1W#T#t=`Nm5zFdoe4a{E>(G$d!t`_tTnw_epvp7?$%29TM%e=a7-bAMWBmY ztW*HXKeqo-)A1OT2L4tf%Kt4U3at?U^L=|e&@-l=j1XQ)m{*=5i>t!;p6^(P(E8xX z?>c?={6dbDMbjW-@Dqv-0v+2q_X{mRO|CFa_&toR>juI_G)22$MDHD;tOIXY?QL0^6?;#9g;tXu$-d0<%+;ME!7PhoW(GJ zy~ODwB6#xhrlhd2_&Bh8cVw2JFhh#i?p3y*bxQ8QU0-@5BEj2Rw%6^Z$_~@j;CrZX zwa#aWA`R(lC;AXAAX@@eyl_Ic$`gcYxAr+&>IX!&CZ>s4`Y zn`Um6-ET8B6cMj9yS-B6byoS{?ou`?t8TK~eUwA4abYaqn}#5JqId{|ZuuOQ*5?2~ z{QF5a@!*LE;@z6rRRLChm4g<*f?pe9rskzee=>R3)6gd$(E$YJy07v-*>w=q2w1C` z53(O9_GpR7v2mx2EWMQ?JRRt16|Ug7ilMCpnM*_$gX`sEQ?{Z4Y&Da2>^`x93*_*w zGa1=*!IgWo*Mr5>+-ZseL+f{@PmJl@AuMt4It(3$VF)xSQ-H_f+tZlejcJysY9iW0 zV=F;9H^{3PkTGwiYOR{0NlPTs$}`vdm1TcV7tR_4?H}(ncxMd?b;E2;+V43E7WyO= zOZ(nZ!$g7uH9<1%V*+>E9p`itiJuyF0SA`|SC z?r>W#_eAuI;!%dPPsM4K0KA%B`%=XK%d!eRQPj%I!)3z1x4ANT;jWy!27?GBm5!aHV5;YDF{5k4MeL`F_?VSA*0&ir+ziP59>Xor&3-I1GO=^R>N zU#6YX&u0jFK~X)c~|Dy`5mqHK#=v-p1np z3+3s~^=thM@w_57FRb}`stXhl8RcJN?8nR*>9aYEB89TIK-MAhgPB1*PTt^+_vCn# zAu^HdCUA;Hp0f~&rjTySGBX|f+yX-77f+N!urZgXHu+T8 zVsannt=(ajq74?P>rQs37cvM>XinJpu-A+ki$k&x`s8sPyYy8Dhy)A@)T#70xfyVI zXO*3qDIVRaFM1S_*a{Sp?h7 zI0=y6C}fV;^z$=(_xYV`?dqIBw+c26=|xfvD!@lF&=k3>5n{DRzU zGvC(t18?ZoNWTF0!tjB-yWS&a!g97=Cv#q&7)eJV_5G%-Bcbf}%^8eZjBq6@f7(MQ zqQkQsfj9?j&I1gtw4tfqW9EP?HLiEH{V$=ua<6P%h>k%|-4S~QDF^oZvFMUSm5RQ@ z)wJ)vbA}V^+oX$iY4uE(|3Xl+TmsT#ma>13CJVw5?&OpB1Qd(D^Y-qgbHfddhTshj z(%*iwKEh8qrs>)binm9W#QtGc77U0)5``#utL<0cS#=s2P3G6m=4LaR{t=jpIr6;* zVYkhevW2|ekhkqAoX_)2=i9Y=KmNXSN$md^-Jc`wftBj5nmLAAtcWE6?PvT8L)&u> z)pvU_c8428YCM~ufN<&y8=1WDl<2TEu_#=YIgIg`XW-{JKO}axoZHUh6Fw`|A<~xR4elz*dsyxN&RgjTL9emS@=D z*oN+rNZo)}taY5KXQS<@t4sM{*O

Jc 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 Lta!2L7tj9-)m5ad literal 0 HcmV?d00001 diff --git a/docs/pictures/eso-dashboard-2.png b/docs/pictures/eso-dashboard-2.png new file mode 100644 index 0000000000000000000000000000000000000000..c5527344ff72821e2579bee62beeadd48fe9c87a GIT binary patch literal 120286 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 literal 0 HcmV?d00001 diff --git a/docs/snippets/dashboard.json b/docs/snippets/dashboard.json new file mode 100644 index 00000000000..c718b822815 --- /dev/null +++ b/docs/snippets/dashboard.json @@ -0,0 +1,984 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 27, + "links": [], + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 27, + "title": "Admission Control Webhook", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 53, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(increase(controller_runtime_webhook_requests_total{service=~\"external-secrets.*\"}[1m])) by (webhook)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "requests by path per minute", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 67, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(controller_runtime_webhook_requests_in_flight{service=~\"external-secrets.*\"}) by (webhook)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "requests in flight", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 80, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(increase(controller_runtime_webhook_requests_total{service=~\"external-secrets.*\"}[1m])) by (code)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "requests by code per minute", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 54, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Oranges", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false + } + }, + "pluginVersion": "9.3.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(rate(controller_runtime_webhook_latency_seconds_bucket{service=~\"external-secrets.*\"}[$__rate_interval])) by (le)", + "legendFormat": "{{le}}", + "range": true, + "refId": "A" + } + ], + "title": "webhook latency", + "type": "heatmap" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 17 + }, + "id": 17, + "panels": [], + "title": "Controllers", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3.4285714285714284, + "x": 0, + "y": 18 + }, + "id": 5, + "maxPerRow": 12, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.3.1", + "repeat": "controller", + "repeatDirection": "h", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(controller_runtime_max_concurrent_reconciles{service=~\"external-secrets.*\",controller=\"$controller\"}) by (controller)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "max concurrent: $controller", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3.4285714285714284, + "x": 0, + "y": 24 + }, + "id": 3, + "maxPerRow": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "repeat": "controller", + "repeatDirection": "h", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(increase(controller_runtime_reconcile_total{service=~\"external-secrets.*\",controller=~\"$controller\"}[1m])) by (result)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "reconcile rate per minute: $controller", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 32 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(controller_runtime_active_workers{service=~\"external-secrets.*\",controller=~\"$controller\"}) by (controller)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "active workers by controller", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 7, + "x": 8, + "y": 32 + }, + "id": 37, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(workqueue_depth{service=~\"external-secrets.*\"}) by (name)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "workqueue depth", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 9, + "x": 15, + "y": 32 + }, + "id": 15, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(increase(externalsecret_provider_api_calls_count{service=~\"external-secrets.*\"}[1m])) by(provider, call, status)", + "legendFormat": "{{provider}}/{{call}}={{status}}", + "range": true, + "refId": "A" + } + ], + "title": "API calls by provider", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3.4285714285714284, + "x": 0, + "y": 41 + }, + "id": 39, + "maxPerRow": 8, + "options": { + "calculate": false, + "cellGap": 1, + "cellValues": { + "unit": "short" + }, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Oranges", + "steps": 10 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "max": "5", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "9.3.1", + "repeat": "controller", + "repeatDirection": "h", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "rate(controller_runtime_reconcile_time_seconds_bucket{service=~\"external-secrets.*\",controller=~\"$controller\"}[$__rate_interval])", + "legendFormat": "{{le}}", + "range": true, + "refId": "A" + } + ], + "title": "reconcile time latency: $controller", + "type": "heatmap" + } + ], + "refresh": false, + "schemaVersion": 37, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": ".*", + "current": { + "selected": false, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "definition": "label_values(controller_runtime_active_workers{service=~\"external-secrets.*\"}, controller)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "controller", + "options": [], + "query": { + "query": "label_values(controller_runtime_active_workers{service=~\"external-secrets.*\"}, controller)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "External Secrets Operator", + "uid": "n4IdKaJVk", + "version": 25, + "weekStart": "" + } \ No newline at end of file diff --git a/pkg/provider/aws/parameterstore/parameterstore.go b/pkg/provider/aws/parameterstore/parameterstore.go index 20f44026e73..1367460afa7 100644 --- a/pkg/provider/aws/parameterstore/parameterstore.go +++ b/pkg/provider/aws/parameterstore/parameterstore.go @@ -31,6 +31,7 @@ import ( esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" "github.com/external-secrets/external-secrets/pkg/find" "github.com/external-secrets/external-secrets/pkg/provider/aws/util" + "github.com/external-secrets/external-secrets/pkg/provider/metrics" ) // https://github.com/external-secrets/external-secrets/issues/644 @@ -79,7 +80,7 @@ func (pm *ParameterStore) getTagsByName(ctx aws.Context, ref *ssm.GetParameterOu } data, err := pm.client.ListTagsForResourceWithContext(ctx, ¶meterTags) - + metrics.ObserveAPICall(metrics.ProviderAWSPS, metrics.CallAWSPSListTagsForResource, err) if err != nil { return nil, fmt.Errorf("error listing tags %w", err) } @@ -93,6 +94,7 @@ func (pm *ParameterStore) DeleteSecret(ctx context.Context, remoteRef esv1beta1. Name: &secretName, } existing, err := pm.client.GetParameterWithContext(ctx, &secretValue) + metrics.ObserveAPICall(metrics.ProviderAWSPS, metrics.CallAWSPSGetParameter, err) var awsError awserr.Error ok := errors.As(err, &awsError) if err != nil && (!ok || awsError.Code() != ssm.ErrCodeParameterNotFound) { @@ -115,6 +117,7 @@ func (pm *ParameterStore) DeleteSecret(ctx context.Context, remoteRef esv1beta1. Name: &secretName, } _, err = pm.client.DeleteParameterWithContext(ctx, deleteInput) + metrics.ObserveAPICall(metrics.ProviderAWSPS, metrics.CallAWSPSDeleteParameter, err) if err != nil { return fmt.Errorf("could not delete parameter %v: %w", secretName, err) } @@ -141,6 +144,7 @@ func (pm *ParameterStore) PushSecret(ctx context.Context, value []byte, remoteRe } existing, err := pm.client.GetParameterWithContext(ctx, &secretValue) + metrics.ObserveAPICall(metrics.ProviderAWSPS, metrics.CallAWSPSGetParameter, err) var awsError awserr.Error ok := errors.As(err, &awsError) if err != nil && (!ok || awsError.Code() != ssm.ErrCodeParameterNotFound) { @@ -196,6 +200,7 @@ func (pm *ParameterStore) setManagedRemoteParameter(ctx context.Context, secretR } _, err := pm.client.PutParameterWithContext(ctx, &secretRequest) + metrics.ObserveAPICall(metrics.ProviderAWSPS, metrics.CallAWSPSPutParameter, err) if err != nil { return fmt.Errorf("unexpected error pushing parameter %v: %w", secretRequest.Name, err) } @@ -235,6 +240,7 @@ func (pm *ParameterStore) findByName(ctx context.Context, ref esv1beta1.External NextToken: nextToken, ParameterFilters: pathFilter, }) + metrics.ObserveAPICall(metrics.ProviderAWSPS, metrics.CallAWSPSDescribeParameter, err) if err != nil { return nil, err } @@ -283,6 +289,7 @@ func (pm *ParameterStore) findByTags(ctx context.Context, ref esv1beta1.External ParameterFilters: filters, NextToken: nextToken, }) + metrics.ObserveAPICall(metrics.ProviderAWSPS, metrics.CallAWSPSDescribeParameter, err) if err != nil { return nil, err } @@ -306,6 +313,7 @@ func (pm *ParameterStore) fetchAndSet(ctx context.Context, data map[string][]byt Name: utilpointer.String(name), WithDecryption: aws.Bool(true), }) + metrics.ObserveAPICall(metrics.ProviderAWSPS, metrics.CallAWSPSGetParameter, err) if err != nil { return util.SanitizeErr(err) } @@ -320,7 +328,7 @@ func (pm *ParameterStore) GetSecret(ctx context.Context, ref esv1beta1.ExternalS Name: &ref.Key, WithDecryption: aws.Bool(true), }) - + metrics.ObserveAPICall(metrics.ProviderAWSPS, metrics.CallAWSPSGetParameter, err) nsf := esv1beta1.NoSecretError{} var nf *ssm.ParameterNotFound if errors.As(err, &nf) || errors.As(err, &nsf) { diff --git a/pkg/provider/aws/secretsmanager/secretsmanager.go b/pkg/provider/aws/secretsmanager/secretsmanager.go index 2e94b969902..cd376c5e1e3 100644 --- a/pkg/provider/aws/secretsmanager/secretsmanager.go +++ b/pkg/provider/aws/secretsmanager/secretsmanager.go @@ -34,6 +34,7 @@ import ( esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" "github.com/external-secrets/external-secrets/pkg/find" "github.com/external-secrets/external-secrets/pkg/provider/aws/util" + "github.com/external-secrets/external-secrets/pkg/provider/metrics" ) // https://github.com/external-secrets/external-secrets/issues/644 @@ -135,6 +136,7 @@ func (sm *SecretsManager) fetch(ctx context.Context, ref esv1beta1.ExternalSecre } } secretOut, err = sm.client.GetSecretValue(getSecretValueInput) + metrics.ObserveAPICall(metrics.ProviderAWSSM, metrics.CallAWSSMGetSecretValue, err) var nf *awssm.ResourceNotFoundException if errors.As(err, &nf) { return nil, esv1beta1.NoSecretErr @@ -171,6 +173,7 @@ func (sm *SecretsManager) DeleteSecret(ctx context.Context, remoteRef esv1beta1. SecretId: &secretName, } awsSecret, err := sm.client.GetSecretValueWithContext(ctx, &secretValue) + metrics.ObserveAPICall(metrics.ProviderAWSSM, metrics.CallAWSSMGetSecretValue, err) var aerr awserr.Error if err != nil { if ok := errors.As(err, &aerr); !ok { @@ -182,6 +185,7 @@ func (sm *SecretsManager) DeleteSecret(ctx context.Context, remoteRef esv1beta1. return err } data, err := sm.client.DescribeSecretWithContext(ctx, &secretInput) + metrics.ObserveAPICall(metrics.ProviderAWSSM, metrics.CallAWSSMDescribeSecret, err) if err != nil { return err } @@ -192,6 +196,7 @@ func (sm *SecretsManager) DeleteSecret(ctx context.Context, remoteRef esv1beta1. SecretId: awsSecret.ARN, } _, err = sm.client.DeleteSecretWithContext(ctx, deleteInput) + metrics.ObserveAPICall(metrics.ProviderAWSSM, metrics.CallAWSSMDeleteSecret, err) return err } @@ -220,6 +225,7 @@ func (sm *SecretsManager) PushSecret(ctx context.Context, value []byte, remoteRe } awsSecret, err := sm.client.GetSecretValueWithContext(ctx, &secretValue) + metrics.ObserveAPICall(metrics.ProviderAWSSM, metrics.CallAWSSMGetSecretValue, err) var aerr awserr.Error if err != nil { if ok := errors.As(err, &aerr); !ok { @@ -227,11 +233,13 @@ func (sm *SecretsManager) PushSecret(ctx context.Context, value []byte, remoteRe } if aerr.Code() == awssm.ErrCodeResourceNotFoundException { _, err = sm.client.CreateSecretWithContext(ctx, &secretRequest) + metrics.ObserveAPICall(metrics.ProviderAWSSM, metrics.CallAWSSMCreateSecret, err) return err } return err } data, err := sm.client.DescribeSecretWithContext(ctx, &secretInput) + metrics.ObserveAPICall(metrics.ProviderAWSSM, metrics.CallAWSSMDescribeSecret, err) if err != nil { return err } @@ -246,6 +254,7 @@ func (sm *SecretsManager) PushSecret(ctx context.Context, value []byte, remoteRe SecretBinary: value, } _, err = sm.client.PutSecretValueWithContext(ctx, input) + metrics.ObserveAPICall(metrics.ProviderAWSSM, metrics.CallAWSSMPutSecretValue, err) return err } @@ -295,6 +304,7 @@ func (sm *SecretsManager) findByName(ctx context.Context, ref esv1beta1.External Filters: filters, NextToken: nextToken, }) + metrics.ObserveAPICall(metrics.ProviderAWSSM, metrics.CallAWSSMListSecrets, err) if err != nil { return nil, err } @@ -350,6 +360,7 @@ func (sm *SecretsManager) findByTags(ctx context.Context, ref esv1beta1.External Filters: filters, NextToken: nextToken, }) + metrics.ObserveAPICall(metrics.ProviderAWSSM, metrics.CallAWSSMListSecrets, err) if err != nil { return nil, err } diff --git a/pkg/provider/azure/keyvault/keyvault.go b/pkg/provider/azure/keyvault/keyvault.go index 30d08500e72..e1ca63b1313 100644 --- a/pkg/provider/azure/keyvault/keyvault.go +++ b/pkg/provider/azure/keyvault/keyvault.go @@ -49,6 +49,7 @@ import ( esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" smmeta "github.com/external-secrets/external-secrets/apis/meta/v1" + "github.com/external-secrets/external-secrets/pkg/provider/metrics" "github.com/external-secrets/external-secrets/pkg/utils" ) @@ -244,12 +245,14 @@ func canDelete(tags map[string]*string, err error) (bool, error) { func (a *Azure) deleteKeyVaultKey(ctx context.Context, keyName string) error { value, err := a.baseClient.GetKey(ctx, *a.provider.VaultURL, keyName, "") + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVGetKey, err) ok, err := canDelete(value.Tags, err) if err != nil { return fmt.Errorf("error getting key %v: %w", keyName, err) } if ok { _, err = a.baseClient.DeleteKey(ctx, *a.provider.VaultURL, keyName) + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVDeleteKey, err) if err != nil { return fmt.Errorf("error deleting key %v: %w", keyName, err) } @@ -259,12 +262,14 @@ func (a *Azure) deleteKeyVaultKey(ctx context.Context, keyName string) error { func (a *Azure) deleteKeyVaultSecret(ctx context.Context, secretName string) error { value, err := a.baseClient.GetSecret(ctx, *a.provider.VaultURL, secretName, "") + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVGetSecret, err) ok, err := canDelete(value.Tags, err) if err != nil { return fmt.Errorf("error getting secret %v: %w", secretName, err) } if ok { _, err = a.baseClient.DeleteSecret(ctx, *a.provider.VaultURL, secretName) + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVDeleteSecret, err) if err != nil { return fmt.Errorf("error deleting secret %v: %w", secretName, err) } @@ -274,12 +279,14 @@ func (a *Azure) deleteKeyVaultSecret(ctx context.Context, secretName string) err func (a *Azure) deleteKeyVaultCertificate(ctx context.Context, certName string) error { value, err := a.baseClient.GetCertificate(ctx, *a.provider.VaultURL, certName, "") + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVGetCertificate, err) ok, err := canDelete(value.Tags, err) if err != nil { return fmt.Errorf("error getting certificate %v: %w", certName, err) } if ok { _, err = a.baseClient.DeleteCertificate(ctx, *a.provider.VaultURL, certName) + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVDeleteCertificate, err) if err != nil { return fmt.Errorf("error deleting certificate %v: %w", certName, err) } @@ -353,6 +360,7 @@ func canCreate(tags map[string]*string, err error) (bool, error) { func (a *Azure) setKeyVaultSecret(ctx context.Context, secretName string, value []byte) error { secret, err := a.baseClient.GetSecret(ctx, *a.provider.VaultURL, secretName, "") + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVGetSecret, err) ok, err := canCreate(secret.Tags, err) if err != nil { return fmt.Errorf("cannot get secret %v: %w", secretName, err) @@ -374,6 +382,7 @@ func (a *Azure) setKeyVaultSecret(ctx context.Context, secretName string, value }, } _, err = a.baseClient.SetSecret(ctx, *a.provider.VaultURL, secretName, secretParams) + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVGetSecret, err) if err != nil { return fmt.Errorf("could not set secret %v: %w", secretName, err) } @@ -387,6 +396,7 @@ func (a *Azure) setKeyVaultCertificate(ctx context.Context, secretName string, v return fmt.Errorf("value from secret is not a valid certificate: %w", err) } cert, err := a.baseClient.GetCertificate(ctx, *a.provider.VaultURL, secretName, "") + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVGetCertificate, err) ok, err := canCreate(cert.Tags, err) if err != nil { return fmt.Errorf("cannot get certificate %v: %w", secretName, err) @@ -405,6 +415,7 @@ func (a *Azure) setKeyVaultCertificate(ctx context.Context, secretName string, v }, } _, err = a.baseClient.ImportCertificate(ctx, *a.provider.VaultURL, secretName, params) + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVImportCertificate, err) if err != nil { return fmt.Errorf("could not import certificate %v: %w", secretName, err) } @@ -441,6 +452,7 @@ func (a *Azure) setKeyVaultKey(ctx context.Context, secretName string, value []b return fmt.Errorf("error unmarshalling key: %w", err) } keyFromVault, err := a.baseClient.GetKey(ctx, *a.provider.VaultURL, secretName, "") + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVGetKey, err) ok, err := canCreate(keyFromVault.Tags, err) if err != nil { return fmt.Errorf("cannot get key %v: %w", secretName, err) @@ -459,6 +471,7 @@ func (a *Azure) setKeyVaultKey(ctx context.Context, secretName string, value []b }, } _, err = a.baseClient.ImportKey(ctx, *a.provider.VaultURL, secretName, params) + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVImportKey, err) if err != nil { return fmt.Errorf("could not import key %v: %w", secretName, err) } @@ -589,6 +602,7 @@ func (a *Azure) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataR // returns a SecretBundle with the secret value // https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault#SecretBundle secretResp, err := a.baseClient.GetSecret(context.Background(), *a.provider.VaultURL, secretName, ref.Version) + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVGetSecret, err) err = parseError(err) if err != nil { return nil, err @@ -601,6 +615,7 @@ func (a *Azure) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataR // returns a CertBundle. We return CER contents of x509 certificate // see: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault#CertificateBundle certResp, err := a.baseClient.GetCertificate(context.Background(), *a.provider.VaultURL, secretName, ref.Version) + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVGetCertificate, err) err = parseError(err) if err != nil { return nil, err @@ -614,6 +629,7 @@ func (a *Azure) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataR // azure kv returns only public keys // see: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault#KeyBundle keyResp, err := a.baseClient.GetKey(context.Background(), *a.provider.VaultURL, secretName, ref.Version) + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVGetKey, err) err = parseError(err) if err != nil { return nil, err @@ -631,6 +647,7 @@ func (a *Azure) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataR func (a *Azure) getSecretTags(ref esv1beta1.ExternalSecretDataRemoteRef) (map[string]*string, error) { _, secretName := getObjType(ref) secretResp, err := a.baseClient.GetSecret(context.Background(), *a.provider.VaultURL, secretName, ref.Version) + metrics.ObserveAPICall(metrics.ProviderAzureKV, metrics.CallAzureKVGetSecret, err) err = parseError(err) if err != nil { return nil, err diff --git a/pkg/provider/gcp/secretmanager/client.go b/pkg/provider/gcp/secretmanager/client.go index 73754ea377f..ed83527fe2f 100644 --- a/pkg/provider/gcp/secretmanager/client.go +++ b/pkg/provider/gcp/secretmanager/client.go @@ -34,6 +34,7 @@ import ( esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" "github.com/external-secrets/external-secrets/pkg/find" + "github.com/external-secrets/external-secrets/pkg/provider/metrics" "github.com/external-secrets/external-secrets/pkg/utils" ) @@ -91,6 +92,7 @@ func (c *Client) DeleteSecret(ctx context.Context, remoteRef esv1beta1.PushRemot gcpSecret, err = c.smClient.GetSecret(ctx, &secretmanagerpb.GetSecretRequest{ Name: fmt.Sprintf("projects/%s/secrets/%s", c.store.ProjectID, remoteRef.GetRemoteKey()), }) + metrics.ObserveAPICall(metrics.ProviderGCPSM, metrics.CallGCPSMGetSecret, err) var gErr *apierror.APIError if errors.As(err, &gErr) { @@ -111,7 +113,9 @@ func (c *Client) DeleteSecret(ctx context.Context, remoteRef esv1beta1.PushRemot deleteSecretVersionReq := &secretmanagerpb.DeleteSecretRequest{ Name: fmt.Sprintf("projects/%s/secrets/%s", c.store.ProjectID, remoteRef.GetRemoteKey()), } - return c.smClient.DeleteSecret(ctx, deleteSecretVersionReq) + err = c.smClient.DeleteSecret(ctx, deleteSecretVersionReq) + metrics.ObserveAPICall(metrics.ProviderGCPSM, metrics.CallGCPSMDeleteSecret, err) + return err } func parseError(err error) error { @@ -145,12 +149,14 @@ func (c *Client) PushSecret(ctx context.Context, payload []byte, remoteRef esv1b gcpSecret, err = c.smClient.GetSecret(ctx, &secretmanagerpb.GetSecretRequest{ Name: fmt.Sprintf("projects/%s/secrets/%s", c.store.ProjectID, remoteRef.GetRemoteKey()), }) + metrics.ObserveAPICall(metrics.ProviderGCPSM, metrics.CallGCPSMGetSecret, err) var gErr *apierror.APIError if err != nil && errors.As(err, &gErr) { if gErr.GRPCStatus().Code() == codes.NotFound { gcpSecret, err = c.smClient.CreateSecret(ctx, createSecretReq) + metrics.ObserveAPICall(metrics.ProviderGCPSM, metrics.CallGCPSMCreateSecret, err) if err != nil { return err } @@ -168,6 +174,7 @@ func (c *Client) PushSecret(ctx context.Context, payload []byte, remoteRef esv1b gcpVersion, err := c.smClient.AccessSecretVersion(ctx, &secretmanagerpb.AccessSecretVersionRequest{ Name: fmt.Sprintf("projects/%s/secrets/%s/versions/latest", c.store.ProjectID, remoteRef.GetRemoteKey()), }) + metrics.ObserveAPICall(metrics.ProviderGCPSM, metrics.CallGCPSMAccessSecretVersion, err) if errors.As(err, &gErr) { if err != nil && gErr.GRPCStatus().Code() != codes.NotFound { @@ -189,7 +196,7 @@ func (c *Client) PushSecret(ctx context.Context, payload []byte, remoteRef esv1b } _, err = c.smClient.AddSecretVersion(ctx, addSecretVersionReq) - + metrics.ObserveAPICall(metrics.ProviderGCPSM, metrics.CallGCPSMAddSecretVersion, err) if err != nil { return err } @@ -224,8 +231,10 @@ func (c *Client) findByName(ctx context.Context, ref esv1beta1.ExternalSecretFin // Call the API. it := c.smClient.ListSecrets(ctx, req) secretMap := make(map[string][]byte) + var resp *secretmanagerpb.Secret + defer metrics.ObserveAPICall(metrics.ProviderGCPSM, metrics.CallGCPSMListSecrets, err) for { - resp, err := it.Next() + resp, err = it.Next() if errors.Is(err, iterator.Done) { break } @@ -280,9 +289,12 @@ func (c *Client) findByTags(ctx context.Context, ref esv1beta1.ExternalSecretFin req.Filter = tagFilter // Call the API. it := c.smClient.ListSecrets(ctx, req) + var resp *secretmanagerpb.Secret + var err error + defer metrics.ObserveAPICall(metrics.ProviderGCPSM, metrics.CallGCPSMListSecrets, err) secretMap := make(map[string][]byte) for { - resp, err := it.Next() + resp, err = it.Next() if errors.Is(err, iterator.Done) { break } @@ -333,6 +345,7 @@ func (c *Client) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretData Name: fmt.Sprintf("projects/%s/secrets/%s/versions/%s", c.store.ProjectID, ref.Key, version), } result, err := c.smClient.AccessSecretVersion(ctx, req) + metrics.ObserveAPICall(metrics.ProviderGCPSM, metrics.CallGCPSMAccessSecretVersion, err) err = parseError(err) if err != nil { return nil, fmt.Errorf(errClientGetSecretAccess, err) diff --git a/pkg/provider/gcp/secretmanager/workload_identity.go b/pkg/provider/gcp/secretmanager/workload_identity.go index ee3f542cd6f..08287f5e8a7 100644 --- a/pkg/provider/gcp/secretmanager/workload_identity.go +++ b/pkg/provider/gcp/secretmanager/workload_identity.go @@ -41,6 +41,7 @@ import ( ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config" esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" + "github.com/external-secrets/external-secrets/pkg/provider/metrics" ) const ( @@ -127,11 +128,13 @@ func (w *workloadIdentity) TokenSource(ctx context.Context, auth esv1beta1.GCPSM gcpSA := sa.Annotations[gcpSAAnnotation] resp, err := w.saTokenGenerator.Generate(ctx, audiences, saKey.Name, saKey.Namespace) + metrics.ObserveAPICall(metrics.ProviderGCPSM, metrics.CallGCPSMGenerateSAToken, err) if err != nil { return nil, fmt.Errorf(errFetchPodToken, err) } idBindToken, err := w.idBindTokenGenerator.Generate(ctx, http.DefaultClient, resp.Status.Token, idPool, idProvider) + metrics.ObserveAPICall(metrics.ProviderGCPSM, metrics.CallGCPSMGenerateIDBindToken, err) if err != nil { return nil, fmt.Errorf(errFetchIBToken, err) } @@ -146,6 +149,7 @@ func (w *workloadIdentity) TokenSource(ctx context.Context, auth esv1beta1.GCPSM Name: fmt.Sprintf("projects/-/serviceAccounts/%s", gcpSA), Scope: secretmanager.DefaultAuthScopes(), }, gax.WithGRPCOptions(grpc.PerRPCCredentials(oauth.TokenSource{TokenSource: oauth2.StaticTokenSource(idBindToken)}))) + metrics.ObserveAPICall(metrics.ProviderGCPSM, metrics.CallGCPSMGenerateAccessToken, err) if err != nil { return nil, fmt.Errorf(errGenAccessToken, err) } diff --git a/pkg/provider/gitlab/gitlab.go b/pkg/provider/gitlab/gitlab.go index 918dc5301be..c32ada1834e 100644 --- a/pkg/provider/gitlab/gitlab.go +++ b/pkg/provider/gitlab/gitlab.go @@ -31,6 +31,7 @@ import ( esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" "github.com/external-secrets/external-secrets/pkg/find" + "github.com/external-secrets/external-secrets/pkg/provider/metrics" "github.com/external-secrets/external-secrets/pkg/utils" ) @@ -243,6 +244,7 @@ func (g *Gitlab) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecret for groupPage := 1; ; groupPage++ { gopts.Page = groupPage groupVars, response, err := g.groupVariablesClient.ListVariables(groupID, gopts) + metrics.ObserveAPICall(metrics.ProviderGitLab, metrics.CallGitLabGroupListVariables, err) if err != nil { return nil, err } @@ -263,6 +265,7 @@ func (g *Gitlab) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecret for projectPage := 1; ; projectPage++ { popts.Page = projectPage projectData, response, err := g.projectVariablesClient.ListVariables(g.projectID, popts) + metrics.ObserveAPICall(metrics.ProviderGitLab, metrics.CallGitLabProjectListVariables, err) if err != nil { return nil, err } @@ -320,9 +323,11 @@ func (g *Gitlab) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretData } data, resp, err := g.projectVariablesClient.GetVariable(g.projectID, ref.Key, vopts) + metrics.ObserveAPICall(metrics.ProviderGitLab, metrics.CallGitLabProjectVariableGet, err) if !isEmptyOrWildcard(g.environment) && resp.StatusCode == http.StatusNotFound { vopts.Filter.EnvironmentScope = "*" data, resp, err = g.projectVariablesClient.GetVariable(g.projectID, ref.Key, vopts) + metrics.ObserveAPICall(metrics.ProviderGitLab, metrics.CallGitLabProjectVariableGet, err) } if resp.StatusCode >= 400 && resp.StatusCode != http.StatusNotFound && err != nil { @@ -346,6 +351,7 @@ func (g *Gitlab) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretData } groupVar, resp, err := g.groupVariablesClient.GetVariable(groupID, ref.Key, nil) + metrics.ObserveAPICall(metrics.ProviderGitLab, metrics.CallGitLabGroupGetVariable, err) if resp.StatusCode >= 400 && resp.StatusCode != http.StatusNotFound && err != nil { return nil, err } @@ -430,6 +436,7 @@ func (g *Gitlab) Close(ctx context.Context) error { func (g *Gitlab) Validate() (esv1beta1.ValidationResult, error) { if g.projectID != "" { _, resp, err := g.projectVariablesClient.ListVariables(g.projectID, nil) + metrics.ObserveAPICall(metrics.ProviderGitLab, metrics.CallGitLabProjectListVariables, err) if err != nil { return esv1beta1.ValidationResultError, fmt.Errorf(errList, err) } else if resp == nil || resp.StatusCode != http.StatusOK { @@ -446,6 +453,7 @@ func (g *Gitlab) Validate() (esv1beta1.ValidationResult, error) { if len(g.groupIDs) > 0 { for _, groupID := range g.groupIDs { _, resp, err := g.groupVariablesClient.ListVariables(groupID, nil) + metrics.ObserveAPICall(metrics.ProviderGitLab, metrics.CallGitLabGroupListVariables, err) if err != nil { return esv1beta1.ValidationResultError, fmt.Errorf(errList, err) } else if resp == nil || resp.StatusCode != http.StatusOK { @@ -460,6 +468,7 @@ func (g *Gitlab) Validate() (esv1beta1.ValidationResult, error) { func (g *Gitlab) ResolveGroupIds() error { if g.inheritFromGroups { projectGroups, resp, err := g.projectsClient.ListProjectsGroups(g.projectID, nil) + metrics.ObserveAPICall(metrics.ProviderGitLab, metrics.CallGitLabListProjectsGroups, err) if resp.StatusCode >= 400 && err != nil { return err } diff --git a/pkg/provider/ibm/provider.go b/pkg/provider/ibm/provider.go index 812b292cb2b..be471d2634a 100644 --- a/pkg/provider/ibm/provider.go +++ b/pkg/provider/ibm/provider.go @@ -31,6 +31,7 @@ import ( 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/provider/metrics" utils "github.com/external-secrets/external-secrets/pkg/utils" ) @@ -185,6 +186,7 @@ func getArbitrarySecret(ibm *providerIBM, secretName *string) ([]byte, error) { SecretType: core.StringPtr(sm.GetSecretOptionsSecretTypeArbitraryConst), ID: secretName, }) + metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err) if err != nil { return nil, err } @@ -201,6 +203,7 @@ func getImportCertSecret(ibm *providerIBM, secretName *string, ref esv1beta1.Ext SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst), ID: secretName, }) + metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err) if err != nil { return nil, err } @@ -220,6 +223,7 @@ func getPublicCertSecret(ibm *providerIBM, secretName *string, ref esv1beta1.Ext SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypePublicCertConst), ID: secretName, }) + metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err) if err != nil { return nil, err } @@ -239,6 +243,7 @@ func getPrivateCertSecret(ibm *providerIBM, secretName *string, ref esv1beta1.Ex SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypePrivateCertConst), ID: secretName, }) + metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err) if err != nil { return nil, err } @@ -258,6 +263,7 @@ func getIamCredentialsSecret(ibm *providerIBM, secretName *string) ([]byte, erro SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst), ID: secretName, }) + metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err) if err != nil { return nil, err } @@ -274,6 +280,7 @@ func getUsernamePasswordSecret(ibm *providerIBM, secretName *string, ref esv1bet SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst), ID: secretName, }) + metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err) if err != nil { return nil, err } @@ -357,6 +364,7 @@ func getSecretByType(ibm *providerIBM, secretName *string, secretType string) (* SecretType: core.StringPtr(secretType), ID: secretName, }) + metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err) if err != nil { return nil, err } @@ -387,6 +395,7 @@ func (ibm *providerIBM) GetSecretMap(ctx context.Context, ref esv1beta1.External SecretType: core.StringPtr(sm.GetSecretOptionsSecretTypeArbitraryConst), ID: &ref.Key, }) + metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err) if err != nil { return nil, err } @@ -411,6 +420,7 @@ func (ibm *providerIBM) GetSecretMap(ctx context.Context, ref esv1beta1.External SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst), ID: &secretName, }) + metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err) if err != nil { return nil, err } @@ -428,6 +438,7 @@ func (ibm *providerIBM) GetSecretMap(ctx context.Context, ref esv1beta1.External SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst), ID: &secretName, }) + metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err) if err != nil { return nil, err } @@ -446,6 +457,7 @@ func (ibm *providerIBM) GetSecretMap(ctx context.Context, ref esv1beta1.External SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst), ID: &secretName, }) + metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err) if err != nil { return nil, err } @@ -463,6 +475,7 @@ func (ibm *providerIBM) GetSecretMap(ctx context.Context, ref esv1beta1.External SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypePublicCertConst), ID: &secretName, }) + metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err) if err != nil { return nil, err } @@ -480,6 +493,7 @@ func (ibm *providerIBM) GetSecretMap(ctx context.Context, ref esv1beta1.External SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypePrivateCertConst), ID: &secretName, }) + metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err) if err != nil { return nil, err } diff --git a/pkg/provider/kubernetes/client.go b/pkg/provider/kubernetes/client.go index 9ac593fb84b..0382ff55d14 100644 --- a/pkg/provider/kubernetes/client.go +++ b/pkg/provider/kubernetes/client.go @@ -24,6 +24,7 @@ import ( esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" "github.com/external-secrets/external-secrets/pkg/find" + "github.com/external-secrets/external-secrets/pkg/provider/metrics" "github.com/external-secrets/external-secrets/pkg/utils" ) @@ -61,6 +62,7 @@ func (c *Client) PushSecret(ctx context.Context, value []byte, remoteRef esv1bet func (c *Client) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) { secret, err := c.userSecretClient.Get(ctx, ref.Key, metav1.GetOptions{}) + metrics.ObserveAPICall(metrics.ProviderKubernetes, metrics.CallKubernetesGetSecret, err) if apierrors.IsNotFound(err) { return nil, esv1beta1.NoSecretError{} } @@ -87,6 +89,7 @@ func (c *Client) findByTags(ctx context.Context, ref esv1beta1.ExternalSecretFin return nil, fmt.Errorf("unable to validate selector tags: %w", err) } secrets, err := c.userSecretClient.List(ctx, metav1.ListOptions{LabelSelector: sel.String()}) + metrics.ObserveAPICall(metrics.ProviderKubernetes, metrics.CallKubernetesListSecrets, err) if err != nil { return nil, fmt.Errorf("unable to list secrets: %w", err) } @@ -103,6 +106,7 @@ func (c *Client) findByTags(ctx context.Context, ref esv1beta1.ExternalSecretFin func (c *Client) findByName(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) { secrets, err := c.userSecretClient.List(ctx, metav1.ListOptions{}) + metrics.ObserveAPICall(metrics.ProviderKubernetes, metrics.CallKubernetesListSecrets, err) if err != nil { return nil, fmt.Errorf("unable to list secrets: %w", err) } diff --git a/pkg/provider/kubernetes/validate.go b/pkg/provider/kubernetes/validate.go index 9d709555e44..70dd0950ace 100644 --- a/pkg/provider/kubernetes/validate.go +++ b/pkg/provider/kubernetes/validate.go @@ -21,6 +21,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" + "github.com/external-secrets/external-secrets/pkg/provider/metrics" "github.com/external-secrets/external-secrets/pkg/utils" ) @@ -79,6 +80,7 @@ func (c *Client) Validate() (esv1beta1.ValidationResult, error) { }, } authReview, err := c.userReviewClient.Create(ctx, &t, metav1.CreateOptions{}) + metrics.ObserveAPICall(metrics.ProviderKubernetes, metrics.CallKubernetesCreateSelfSubjectRulesReview, err) if err != nil { return esv1beta1.ValidationResultUnknown, fmt.Errorf("could not verify if client is valid: %w", err) } diff --git a/pkg/provider/metrics/metrics.go b/pkg/provider/metrics/metrics.go new file mode 100644 index 00000000000..993aae38c10 --- /dev/null +++ b/pkg/provider/metrics/metrics.go @@ -0,0 +1,116 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package metrics + +import ( + "github.com/prometheus/client_golang/prometheus" + "sigs.k8s.io/controller-runtime/pkg/metrics" +) + +const ( + ExternalSecretSubsystem = "externalsecret" + providerAPICalls = "provider_api_calls_count" +) + +const ( + ProviderAWSSM = "AWS/SecretsManager" + CallAWSSMGetSecretValue = "GetSecretValue" + CallAWSSMDescribeSecret = "DescribeSecret" + CallAWSSMDeleteSecret = "DeleteSecret" + CallAWSSMCreateSecret = "CreateSecret" + CallAWSSMPutSecretValue = "PutSecretValue" + CallAWSSMListSecrets = "ListSecrets" + + ProviderAWSPS = "AWS/ParameterStore" + CallAWSPSGetParameter = "GetParameter" + CallAWSPSPutParameter = "PutParameter" + CallAWSPSDeleteParameter = "DeleteParameter" + CallAWSPSDescribeParameter = "DescribeParameter" + CallAWSPSListTagsForResource = "ListTagsForResource" + + ProviderAzureKV = "Azure/KeyVault" + CallAzureKVGetKey = "GetKey" + CallAzureKVDeleteKey = "DeleteKey" + CallAzureKVImportKey = "ImportKey" + CallAzureKVGetSecret = "GetSecret" + CallAzureKVDeleteSecret = "DeleteSecret" + CallAzureKVGetCertificate = "GetCertificate" + CallAzureKVDeleteCertificate = "DeleteCertificate" + CallAzureKVImportCertificate = "ImportCertificate" + + ProviderGCPSM = "GCP/SecretManager" + CallGCPSMGetSecret = "GetSecret" + CallGCPSMDeleteSecret = "DeleteSecret" + CallGCPSMCreateSecret = "CreateSecret" + CallGCPSMAccessSecretVersion = "AccessSecretVersion" + CallGCPSMAddSecretVersion = "AddSecretVersion" + CallGCPSMListSecrets = "ListSecrets" + CallGCPSMGenerateSAToken = "GenerateServiceAccountToken" + CallGCPSMGenerateIDBindToken = "GenerateIDBindToken" + CallGCPSMGenerateAccessToken = "GenerateAccessToken" + + ProviderHCVault = "HashiCorp/Vault" + CallHCVaultLogin = "Login" + CallHCVaultRevokeSelf = "RevokeSelf" + CallHCVaultLookupSelf = "LookupSelf" + CallHCVaultReadSecretData = "ReadSecretData" + CallHCVaultWriteSecretData = "WriteSecretData" + CallHCVaultDeleteSecret = "DeleteSecret" + CallHCVaultListSecrets = "ListSecrets" + + ProviderKubernetes = "Kubernetes" + CallKubernetesGetSecret = "GetSecret" + CallKubernetesListSecrets = "ListSecrets" + CallKubernetesCreateSelfSubjectRulesReview = "CreateSelfSubjectRulesReview" + + ProviderIBMSM = "IBM/SecretsManager" + CallIBMSMGetSecret = "GetSecret" + + ProviderWebhook = "Webhook" + CallWebhookHTTPReq = "HTTPRequest" + + ProviderGitLab = "GitLab" + CallGitLabListProjectsGroups = "ListProjectsGroups" + CallGitLabProjectVariableGet = "ProjectVariableGet" + CallGitLabProjectListVariables = "ProjectVariablesList" + CallGitLabGroupGetVariable = "GroupVariableGet" + CallGitLabGroupListVariables = "GroupVariablesList" + + StatusError = "error" + StatusSuccess = "success" +) + +var ( + syncCallsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ + Subsystem: ExternalSecretSubsystem, + Name: providerAPICalls, + Help: "Number of API calls towards the secret provider", + }, []string{"provider", "call", "status"}) +) + +func ObserveAPICall(provider, call string, err error) { + syncCallsTotal.WithLabelValues(provider, call, deriveStatus(err)).Inc() +} + +func deriveStatus(err error) string { + if err != nil { + return StatusError + } + return StatusSuccess +} + +func init() { + metrics.Registry.MustRegister(syncCallsTotal) +} diff --git a/pkg/provider/vault/vault.go b/pkg/provider/vault/vault.go index 40110324bb4..69430ec06bd 100644 --- a/pkg/provider/vault/vault.go +++ b/pkg/provider/vault/vault.go @@ -49,6 +49,7 @@ import ( "github.com/external-secrets/external-secrets/pkg/cache" "github.com/external-secrets/external-secrets/pkg/feature" "github.com/external-secrets/external-secrets/pkg/find" + "github.com/external-secrets/external-secrets/pkg/provider/metrics" "github.com/external-secrets/external-secrets/pkg/utils" ) @@ -415,10 +416,12 @@ func (v *client) DeleteSecret(ctx context.Context, remoteRef esv1beta1.PushRemot return nil } _, err = v.logical.DeleteWithContext(ctx, path) + metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultDeleteSecret, err) if err != nil { return fmt.Errorf("could not delete secret %v: %w", remoteRef.GetRemoteKey(), err) } _, err = v.logical.DeleteWithContext(ctx, metaPath) + metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultDeleteSecret, err) if err != nil { return fmt.Errorf("could not delete secret metadata %v: %w", remoteRef.GetRemoteKey(), err) } @@ -470,11 +473,13 @@ func (v *client) PushSecret(ctx context.Context, value []byte, remoteRef esv1bet return nil } _, err = v.logical.WriteWithContext(ctx, metaPath, label) + metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultWriteSecretData, err) if err != nil { return err } // Otherwise, create or update the version. _, err = v.logical.WriteWithContext(ctx, path, secretToPush) + metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultWriteSecretData, err) return err } @@ -555,6 +560,7 @@ func (v *client) listSecrets(ctx context.Context, path string) ([]string, error) return nil, err } secret, err := v.logical.ListWithContext(ctx, url) + metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultListSecrets, err) if err != nil { return nil, fmt.Errorf(errReadSecret, err) } @@ -593,6 +599,7 @@ func (v *client) readSecretMetadata(ctx context.Context, path string) (map[strin return nil, err } secret, err := v.logical.ReadWithDataWithContext(ctx, url, nil) + metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultReadSecretData, err) if err != nil { return nil, fmt.Errorf(errReadSecret, err) } @@ -854,6 +861,7 @@ func (v *client) readSecret(ctx context.Context, path, version string) (map[stri params["version"] = []string{version} } vaultSecret, err := v.logical.ReadWithDataWithContext(ctx, dataPath, params) + metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultReadSecretData, err) if err != nil { return nil, fmt.Errorf(errReadSecret, err) } @@ -1193,6 +1201,7 @@ func (v *client) serviceAccountToken(ctx context.Context, serviceAccountRef esme func checkToken(ctx context.Context, token Token) (bool, error) { // https://www.vaultproject.io/api-docs/auth/token#lookup-a-token-self resp, err := token.LookupSelfWithContext(ctx) + metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultLookupSelf, err) if err != nil { return false, err } @@ -1214,6 +1223,7 @@ func revokeTokenIfValid(ctx context.Context, client Client) error { } if valid { err = client.AuthToken().RevokeSelfWithContext(ctx, client.Token()) + metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultRevokeSelf, err) if err != nil { return fmt.Errorf(errVaultRevokeToken, err) } @@ -1235,6 +1245,7 @@ func (v *client) requestTokenWithAppRoleRef(ctx context.Context, appRole *esv1be return err } _, err = v.auth.Login(ctx, appRoleClient) + metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultLogin, err) if err != nil { return err } @@ -1251,6 +1262,7 @@ func (v *client) requestTokenWithKubernetesAuth(ctx context.Context, kubernetesA return err } _, err = v.auth.Login(ctx, k) + metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultLogin, err) if err != nil { return err } @@ -1315,6 +1327,7 @@ func (v *client) requestTokenWithLdapAuth(ctx context.Context, ldapAuth *esv1bet return err } _, err = v.auth.Login(ctx, l) + metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultLogin, err) if err != nil { return err } @@ -1351,6 +1364,7 @@ func (v *client) requestTokenWithJwtAuth(ctx context.Context, jwtAuth *esv1beta1 } url := strings.Join([]string{"auth", jwtAuth.Path, "login"}, "/") vaultResult, err := v.logical.WriteWithContext(ctx, url, parameters) + metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultWriteSecretData, err) if err != nil { return err } @@ -1385,6 +1399,7 @@ func (v *client) requestTokenWithCertAuth(ctx context.Context, certAuth *esv1bet url := strings.Join([]string{"auth", "cert", "login"}, "/") vaultResult, err := v.logical.WriteWithContext(ctx, url, nil) + metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultWriteSecretData, err) if err != nil { return fmt.Errorf(errVaultRequest, err) } diff --git a/pkg/provider/webhook/webhook.go b/pkg/provider/webhook/webhook.go index 84cc4b8d72b..48cc6ed9ef4 100644 --- a/pkg/provider/webhook/webhook.go +++ b/pkg/provider/webhook/webhook.go @@ -34,6 +34,7 @@ import ( esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" + "github.com/external-secrets/external-secrets/pkg/provider/metrics" "github.com/external-secrets/external-secrets/pkg/template/v2" "github.com/external-secrets/external-secrets/pkg/utils" ) @@ -280,6 +281,7 @@ func (w *WebHook) getWebhookData(ctx context.Context, provider *esv1beta1.Webhoo } resp, err := w.http.Do(req) + metrics.ObserveAPICall(metrics.ProviderWebhook, metrics.CallWebhookHTTPReq, err) if err != nil { return nil, fmt.Errorf("failed to call endpoint: %w", err) } From 44bb3c4c03606dec529a48f3eeb87d0864f29825 Mon Sep 17 00:00:00 2001 From: Kendall Masse Date: Mon, 27 Feb 2023 17:14:53 -0500 Subject: [PATCH 34/62] =?UTF-8?q?:sparkles:=20webhook=20provider:=20suppor?= =?UTF-8?q?t=20DeletionPolicy=3DDelete=20(external-secrets#1=E2=80=A6=20(#?= =?UTF-8?q?2066)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: DeletionPolicy support for webhook provider (external-secrets#1958) Signed-off-by: ArtificialQualia * add note to webhook provider docs about deletionPolicy Signed-off-by: ArtificialQualia --------- Signed-off-by: ArtificialQualia --- docs/introduction/stability-support.md | 2 +- docs/provider/webhook.md | 3 +++ pkg/provider/webhook/webhook.go | 3 +++ pkg/provider/webhook/webhook_test.go | 15 +++++++++++++-- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/docs/introduction/stability-support.md b/docs/introduction/stability-support.md index 08a1a84cf85..8d491fd788f 100644 --- a/docs/introduction/stability-support.md +++ b/docs/introduction/stability-support.md @@ -59,7 +59,7 @@ The following table show the support for features across different providers. | Oracle Vault | | | | | x | | | | Akeyless | | | | | x | | | | 1Password | x | | | | x | | | -| Generic Webhook | | | | | | | | +| Generic Webhook | | | | | | | x | | senhasegura DSM | | | | | x | | | | Doppler | x | | | | x | | | diff --git a/docs/provider/webhook.md b/docs/provider/webhook.md index f6dd0acbdf5..04caeabf1ad 100644 --- a/docs/provider/webhook.md +++ b/docs/provider/webhook.md @@ -71,6 +71,9 @@ data: Webhook does not support authorization, other than what can be sent by generating http headers +!!! note + If a webhook endpoint for a given `ExternalSecret` returns a 404 status code, the secret is considered to have been deleted. This will trigger the `deletionPolicy` set on the `ExternalSecret`. + ### Templating Generic WebHook provider uses the templating engine to generate the API call. It can be used in the url, headers, body and result.jsonPath fields. diff --git a/pkg/provider/webhook/webhook.go b/pkg/provider/webhook/webhook.go index 48cc6ed9ef4..8d54c34d72c 100644 --- a/pkg/provider/webhook/webhook.go +++ b/pkg/provider/webhook/webhook.go @@ -286,6 +286,9 @@ func (w *WebHook) getWebhookData(ctx context.Context, provider *esv1beta1.Webhoo return nil, fmt.Errorf("failed to call endpoint: %w", err) } defer resp.Body.Close() + if resp.StatusCode == 404 { + return nil, esv1beta1.NoSecretError{} + } if resp.StatusCode < 200 || resp.StatusCode >= 300 { return nil, fmt.Errorf("endpoint gave error %s", resp.Status) } diff --git a/pkg/provider/webhook/webhook_test.go b/pkg/provider/webhook/webhook_test.go index e7739101af9..2edc13fba54 100644 --- a/pkg/provider/webhook/webhook_test.go +++ b/pkg/provider/webhook/webhook_test.go @@ -75,7 +75,7 @@ args: want: err: failed to call endpoint --- -case: error not found +case: error no secret err args: url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }} key: testkey @@ -84,7 +84,18 @@ args: response: not found want: path: /api/getsecret?id=testkey&version=1 - err: endpoint gave error 404 + err: ` + esv1beta1.NoSecretErr.Error() + ` +--- +case: error server error +args: + url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }} + key: testkey + version: 1 + statuscode: 500 + response: server error +want: + path: /api/getsecret?id=testkey&version=1 + err: endpoint gave error 500 --- case: error bad json args: From 2766c6d5f52f699aa1088269e51dd76c62e52045 Mon Sep 17 00:00:00 2001 From: Pedro Parra Ortega Date: Mon, 27 Feb 2023 23:22:33 +0100 Subject: [PATCH 35/62] refactor keeper auth configuration (#2052) Signed-off-by: Pedro Parra Ortega --- .../secretstore_keepersecurity_types.go | 17 +- .../v1beta1/zz_generated.deepcopy.go | 26 +-- ...ternal-secrets.io_clustersecretstores.yaml | 130 ++----------- .../external-secrets.io_secretstores.yaml | 130 ++----------- deploy/crds/bundle.yaml | 174 +++--------------- docs/api/spec.md | 88 +-------- docs/provider/keeper-security.md | 4 +- .../snippets/keepersecurity-secret-store.yaml | 19 +- pkg/provider/keepersecurity/provider.go | 75 ++------ 9 files changed, 84 insertions(+), 579 deletions(-) diff --git a/apis/externalsecrets/v1beta1/secretstore_keepersecurity_types.go b/apis/externalsecrets/v1beta1/secretstore_keepersecurity_types.go index aa0e6d76c3a..e3e85dedb77 100644 --- a/apis/externalsecrets/v1beta1/secretstore_keepersecurity_types.go +++ b/apis/externalsecrets/v1beta1/secretstore_keepersecurity_types.go @@ -18,18 +18,7 @@ import smmeta "github.com/external-secrets/external-secrets/apis/meta/v1" // KeeperSecurityProvider Configures a store to sync secrets using Keeper Security. type KeeperSecurityProvider struct { - Auth *KeeperSecurityAuth `json:"auth"` - - // Keeper Url from which the secrets to be fetched from. - Hostname string `json:"hostname"` - FolderID string `json:"folderID"` -} - -// KeeperSecurityAuth Configuration used to authenticate with KeeperSecurity. -type KeeperSecurityAuth struct { - AppKey smmeta.SecretKeySelector `json:"appKeySecretRef"` - AppOwnerPublicKey smmeta.SecretKeySelector `json:"appOwnerPublicKeySecretRef"` - ClientID smmeta.SecretKeySelector `json:"clientIdSecretRef"` - PrivateKey smmeta.SecretKeySelector `json:"privateKeySecretRef"` - ServerPublicKeyID smmeta.SecretKeySelector `json:"serverPublicKeyIdSecretRef"` + Auth smmeta.SecretKeySelector `json:"authRef"` + Hostname string `json:"hostname"` + FolderID string `json:"folderID"` } diff --git a/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go b/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go index 08e642f82ba..bd18e46f7da 100644 --- a/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go +++ b/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go @@ -1291,34 +1291,10 @@ func (in *IBMProvider) DeepCopy() *IBMProvider { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *KeeperSecurityAuth) DeepCopyInto(out *KeeperSecurityAuth) { - *out = *in - in.AppKey.DeepCopyInto(&out.AppKey) - in.AppOwnerPublicKey.DeepCopyInto(&out.AppOwnerPublicKey) - in.ClientID.DeepCopyInto(&out.ClientID) - in.PrivateKey.DeepCopyInto(&out.PrivateKey) - in.ServerPublicKeyID.DeepCopyInto(&out.ServerPublicKeyID) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeeperSecurityAuth. -func (in *KeeperSecurityAuth) DeepCopy() *KeeperSecurityAuth { - if in == nil { - return nil - } - out := new(KeeperSecurityAuth) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KeeperSecurityProvider) DeepCopyInto(out *KeeperSecurityProvider) { *out = *in - if in.Auth != nil { - in, out := &in.Auth, &out.Auth - *out = new(KeeperSecurityAuth) - (*in).DeepCopyInto(*out) - } + in.Auth.DeepCopyInto(&out.Auth) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeeperSecurityProvider. diff --git a/config/crds/bases/external-secrets.io_clustersecretstores.yaml b/config/crds/bases/external-secrets.io_clustersecretstores.yaml index 662655f014e..b23a3cde6cc 100644 --- a/config/crds/bases/external-secrets.io_clustersecretstores.yaml +++ b/config/crds/bases/external-secrets.io_clustersecretstores.yaml @@ -2367,125 +2367,31 @@ spec: description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider properties: - auth: - description: KeeperSecurityAuth Configuration used to authenticate - with KeeperSecurity. + authRef: + description: A reference to a specific 'key' within a Secret + resource, In some instances, `key` is a required field. properties: - appKeySecretRef: - description: A reference to a specific 'key' within a - Secret resource, In some instances, `key` is a required - field. - properties: - key: - description: The key of the entry in the Secret resource's - `data` field to be used. Some instances of this - field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being - referred to. - type: string - namespace: - description: Namespace of the resource being referred - to. Ignored if referent is not cluster-scoped. cluster-scoped - defaults to the namespace of the referent. - type: string - type: object - appOwnerPublicKeySecretRef: - description: A reference to a specific 'key' within a - Secret resource, In some instances, `key` is a required - field. - properties: - key: - description: The key of the entry in the Secret resource's - `data` field to be used. Some instances of this - field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being - referred to. - type: string - namespace: - description: Namespace of the resource being referred - to. Ignored if referent is not cluster-scoped. cluster-scoped - defaults to the namespace of the referent. - type: string - type: object - clientIdSecretRef: - description: A reference to a specific 'key' within a - Secret resource, In some instances, `key` is a required - field. - properties: - key: - description: The key of the entry in the Secret resource's - `data` field to be used. Some instances of this - field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being - referred to. - type: string - namespace: - description: Namespace of the resource being referred - to. Ignored if referent is not cluster-scoped. cluster-scoped - defaults to the namespace of the referent. - type: string - type: object - privateKeySecretRef: - description: A reference to a specific 'key' within a - Secret resource, In some instances, `key` is a required - field. - properties: - key: - description: The key of the entry in the Secret resource's - `data` field to be used. Some instances of this - field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being - referred to. - type: string - namespace: - description: Namespace of the resource being referred - to. Ignored if referent is not cluster-scoped. cluster-scoped - defaults to the namespace of the referent. - type: string - type: object - serverPublicKeyIdSecretRef: - description: A reference to a specific 'key' within a - Secret resource, In some instances, `key` is a required - field. - properties: - key: - description: The key of the entry in the Secret resource's - `data` field to be used. Some instances of this - field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being - referred to. - type: string - namespace: - description: Namespace of the resource being referred - to. Ignored if referent is not cluster-scoped. cluster-scoped - defaults to the namespace of the referent. - type: string - type: object - required: - - appKeySecretRef - - appOwnerPublicKeySecretRef - - clientIdSecretRef - - privateKeySecretRef - - serverPublicKeyIdSecretRef + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this field + may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred + to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string type: object folderID: type: string hostname: - description: Keeper Url from which the secrets to be fetched - from. type: string required: - - auth + - authRef - folderID - hostname type: object diff --git a/config/crds/bases/external-secrets.io_secretstores.yaml b/config/crds/bases/external-secrets.io_secretstores.yaml index 1bf196e4eec..3633745f468 100644 --- a/config/crds/bases/external-secrets.io_secretstores.yaml +++ b/config/crds/bases/external-secrets.io_secretstores.yaml @@ -2367,125 +2367,31 @@ spec: description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider properties: - auth: - description: KeeperSecurityAuth Configuration used to authenticate - with KeeperSecurity. + authRef: + description: A reference to a specific 'key' within a Secret + resource, In some instances, `key` is a required field. properties: - appKeySecretRef: - description: A reference to a specific 'key' within a - Secret resource, In some instances, `key` is a required - field. - properties: - key: - description: The key of the entry in the Secret resource's - `data` field to be used. Some instances of this - field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being - referred to. - type: string - namespace: - description: Namespace of the resource being referred - to. Ignored if referent is not cluster-scoped. cluster-scoped - defaults to the namespace of the referent. - type: string - type: object - appOwnerPublicKeySecretRef: - description: A reference to a specific 'key' within a - Secret resource, In some instances, `key` is a required - field. - properties: - key: - description: The key of the entry in the Secret resource's - `data` field to be used. Some instances of this - field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being - referred to. - type: string - namespace: - description: Namespace of the resource being referred - to. Ignored if referent is not cluster-scoped. cluster-scoped - defaults to the namespace of the referent. - type: string - type: object - clientIdSecretRef: - description: A reference to a specific 'key' within a - Secret resource, In some instances, `key` is a required - field. - properties: - key: - description: The key of the entry in the Secret resource's - `data` field to be used. Some instances of this - field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being - referred to. - type: string - namespace: - description: Namespace of the resource being referred - to. Ignored if referent is not cluster-scoped. cluster-scoped - defaults to the namespace of the referent. - type: string - type: object - privateKeySecretRef: - description: A reference to a specific 'key' within a - Secret resource, In some instances, `key` is a required - field. - properties: - key: - description: The key of the entry in the Secret resource's - `data` field to be used. Some instances of this - field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being - referred to. - type: string - namespace: - description: Namespace of the resource being referred - to. Ignored if referent is not cluster-scoped. cluster-scoped - defaults to the namespace of the referent. - type: string - type: object - serverPublicKeyIdSecretRef: - description: A reference to a specific 'key' within a - Secret resource, In some instances, `key` is a required - field. - properties: - key: - description: The key of the entry in the Secret resource's - `data` field to be used. Some instances of this - field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being - referred to. - type: string - namespace: - description: Namespace of the resource being referred - to. Ignored if referent is not cluster-scoped. cluster-scoped - defaults to the namespace of the referent. - type: string - type: object - required: - - appKeySecretRef - - appOwnerPublicKeySecretRef - - clientIdSecretRef - - privateKeySecretRef - - serverPublicKeyIdSecretRef + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this field + may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred + to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string type: object folderID: type: string hostname: - description: Keeper Url from which the secrets to be fetched - from. type: string required: - - auth + - authRef - folderID - hostname type: object diff --git a/deploy/crds/bundle.yaml b/deploy/crds/bundle.yaml index 9fb6bfd22f7..8c7784e3233 100644 --- a/deploy/crds/bundle.yaml +++ b/deploy/crds/bundle.yaml @@ -2176,88 +2176,25 @@ spec: keepersecurity: description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider properties: - auth: - description: KeeperSecurityAuth Configuration used to authenticate with KeeperSecurity. + authRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. properties: - appKeySecretRef: - description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. - type: string - type: object - appOwnerPublicKeySecretRef: - description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. - type: string - type: object - clientIdSecretRef: - description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. - type: string - type: object - privateKeySecretRef: - description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. - type: string - type: object - serverPublicKeyIdSecretRef: - description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. - type: string - type: object - required: - - appKeySecretRef - - appOwnerPublicKeySecretRef - - clientIdSecretRef - - privateKeySecretRef - - serverPublicKeyIdSecretRef + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string type: object folderID: type: string hostname: - description: Keeper Url from which the secrets to be fetched from. type: string required: - - auth + - authRef - folderID - hostname type: object @@ -5557,88 +5494,25 @@ spec: keepersecurity: description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider properties: - auth: - description: KeeperSecurityAuth Configuration used to authenticate with KeeperSecurity. + authRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. properties: - appKeySecretRef: - description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. - type: string - type: object - appOwnerPublicKeySecretRef: - description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. - type: string - type: object - clientIdSecretRef: - description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. - type: string - type: object - privateKeySecretRef: - description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. - type: string - type: object - serverPublicKeyIdSecretRef: - description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. - type: string - type: object - required: - - appKeySecretRef - - appOwnerPublicKeySecretRef - - clientIdSecretRef - - privateKeySecretRef - - serverPublicKeyIdSecretRef + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string type: object folderID: type: string hostname: - description: Keeper Url from which the secrets to be fetched from. type: string required: - - auth + - authRef - folderID - hostname type: object diff --git a/docs/api/spec.md b/docs/api/spec.md index 80081a305de..922d18ec8d9 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -3425,85 +3425,6 @@ string -

KeeperSecurityAuth -

-

-(Appears on: -KeeperSecurityProvider) -

-

-

KeeperSecurityAuth Configuration used to authenticate with KeeperSecurity.

-

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FieldDescription
-appKeySecretRef
- - -External Secrets meta/v1.SecretKeySelector - - -
-
-appOwnerPublicKeySecretRef
- - -External Secrets meta/v1.SecretKeySelector - - -
-
-clientIdSecretRef
- - -External Secrets meta/v1.SecretKeySelector - - -
-
-privateKeySecretRef
- - -External Secrets meta/v1.SecretKeySelector - - -
-
-serverPublicKeyIdSecretRef
- - -External Secrets meta/v1.SecretKeySelector - - -
-

KeeperSecurityProvider

@@ -3523,10 +3444,10 @@ External Secrets meta/v1.SecretKeySelector -auth
+authRef
- -KeeperSecurityAuth + +External Secrets meta/v1.SecretKeySelector @@ -3541,7 +3462,6 @@ string
-

Keeper Url from which the secrets to be fetched from.

@@ -5185,7 +5105,7 @@ External Secrets meta/v1.SecretKeySelector

Error indicates that there is a misconfiguration.

0

-

Ready indicates that the client is configured correctly +

Ready indicates that the client is confgured correctly and can be used.

1

diff --git a/docs/provider/keeper-security.md b/docs/provider/keeper-security.md index 0923f078ada..74d47cec020 100644 --- a/docs/provider/keeper-security.md +++ b/docs/provider/keeper-security.md @@ -13,7 +13,7 @@ KSM can authenticate using *One Time Access Token* or *Secret Manager Configurat You can find the documentation for the Secret Manager Configuration creation [here](https://docs.keeper.io/secrets-manager/secrets-manager/about/secrets-manager-configuration). Make sure you add the proper permissions to your device in order to be able to read and write secrets -Once you have created your SMC, you will get a config.json file containing the following keys: +Once you have created your SMC, you will get a config.json file or a base64 json encoded string containing the following keys: - `hostname` - `clientId` - `privateKey` @@ -21,7 +21,7 @@ Once you have created your SMC, you will get a config.json file containing the f - `appKey` - `appOwnerPublicKey` -This config will be required to create your secretStores +This base64 encoded jsong string will be required to create your secretStores ## Important note about this documentation _**The KepeerSecurity calls the entries in vaults 'Records'. These docs use the same term.**_ diff --git a/docs/snippets/keepersecurity-secret-store.yaml b/docs/snippets/keepersecurity-secret-store.yaml index 09513bbedf9..0213ec63a54 100644 --- a/docs/snippets/keepersecurity-secret-store.yaml +++ b/docs/snippets/keepersecurity-secret-store.yaml @@ -7,20 +7,7 @@ spec: provider: keepersecurity: hostname: keepersecurity.eu - auth: - appKeySecretRef: - name: keeper-configuration - key: appKey - appOwnerPublicKeySecretRef: - name: keeper-configuration - key: appOwnerPublicKey - privateKeySecretRef: - name: keeper-configuration - key: privateKey - serverPublicKeyIdSecretRef: - name: keeper-configuration - key: serverPublicKeyId - clientIdSecretRef: - name: keeper-configuration - key: clientId + authRef: # Refer to a kubernetes secret which holds the base64 encoded json string for the configuration + name: keeper-configuration + key: auth folderID: 1qdsiewFW-U # Folder ID where the secrets can be pushed. It requires write permissions diff --git a/pkg/provider/keepersecurity/provider.go b/pkg/provider/keepersecurity/provider.go index c88ccf0905a..b4eb1e1e6f3 100644 --- a/pkg/provider/keepersecurity/provider.go +++ b/pkg/provider/keepersecurity/provider.go @@ -25,7 +25,6 @@ import ( kclient "sigs.k8s.io/controller-runtime/pkg/client" esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" - smmeta "github.com/external-secrets/external-secrets/apis/meta/v1" "github.com/external-secrets/external-secrets/pkg/utils" ) @@ -36,11 +35,7 @@ const ( errKeeperSecurityNilSpecProvider = "nil spec.provider" errKeeperSecurityNilSpecProviderKeeperSecurity = "nil spec.provider.keepersecurity" errKeeperSecurityStoreMissingAuth = "missing: spec.provider.keepersecurity.auth" - errKeeperSecurityStoreMissingAppKey = "missing: spec.provider.keepersecurity.auth.appKeySecretRef %w" - errKeeperSecurityStoreMissingAppOwnerPublicKey = "missing: spec.provider.keepersecurity.auth.appOwnerPublicKeySecretRef %w" - errKeeperSecurityStoreMissingClientID = "missing: spec.provider.keepersecurity.auth.clientIdSecretRef %w" - errKeeperSecurityStoreMissingPrivateKey = "missing: spec.provider.keepersecurity.auth.privateKeySecretRef %w" - errKeeperSecurityStoreMissingServerPublicKeyID = "missing: spec.provider.keepersecurity.auth.serverPublicKeyIDSecretRef %w" + errKeeperSecurityStoreMissingFolderID = "missing: spec.provider.keepersecurity.folderID" errKeeperSecurityStoreInvalidConnectHost = "unable to parse URL: spec.provider.keepersecurity.connectHost: %w" errInvalidClusterStoreMissingK8sSecretNamespace = "invalid ClusterSecretStore: missing KeeperSecurity k8s Auth Secret Namespace" errFetchK8sSecret = "could not fetch k8s Secret: %w" @@ -74,7 +69,7 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore, keeperStore := storeSpec.Provider.KeeperSecurity isClusterKind := store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind - clientConfig, err := getKeeperSecurityConfig(ctx, keeperStore, kube, isClusterKind, namespace) + clientConfig, err := getKeeperSecurityAuth(ctx, keeperStore, kube, isClusterKind, namespace) if err != nil { return nil, fmt.Errorf(errKeeperSecurityUnableToCreateConfig, err) } @@ -114,69 +109,21 @@ func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error { return fmt.Errorf(errKeeperSecurityStoreInvalidConnectHost, err) } - if config.Auth == nil { + if err := utils.ValidateSecretSelector(store, config.Auth); err != nil { return fmt.Errorf(errKeeperSecurityStoreMissingAuth) } - - if err := utils.ValidateSecretSelector(store, config.Auth.AppKey); err != nil { - return fmt.Errorf(errKeeperSecurityStoreMissingAppKey, err) - } - - if err := utils.ValidateSecretSelector(store, config.Auth.AppOwnerPublicKey); err != nil { - return fmt.Errorf(errKeeperSecurityStoreMissingAppOwnerPublicKey, err) - } - - if err := utils.ValidateSecretSelector(store, config.Auth.PrivateKey); err != nil { - return fmt.Errorf(errKeeperSecurityStoreMissingPrivateKey, err) - } - - if err := utils.ValidateSecretSelector(store, config.Auth.ClientID); err != nil { - return fmt.Errorf(errKeeperSecurityStoreMissingClientID, err) - } - - if err := utils.ValidateSecretSelector(store, config.Auth.ServerPublicKeyID); err != nil { - return fmt.Errorf(errKeeperSecurityStoreMissingServerPublicKeyID, err) + if config.FolderID == "" { + return fmt.Errorf(errKeeperSecurityStoreMissingFolderID) } return nil } -func getKeeperSecurityConfig(ctx context.Context, store *esv1beta1.KeeperSecurityProvider, kube kclient.Client, isClusterKind bool, namespace string) (map[string]string, error) { +func getKeeperSecurityAuth(ctx context.Context, store *esv1beta1.KeeperSecurityProvider, kube kclient.Client, isClusterKind bool, namespace string) (string, error) { auth := store.Auth - apiKey, err := getAuthParameter(ctx, auth.AppKey, kube, isClusterKind, namespace) - if err != nil { - return nil, err - } - appOwnerPublicKey, err := getAuthParameter(ctx, auth.AppOwnerPublicKey, kube, isClusterKind, namespace) - if err != nil { - return nil, err - } - clientID, err := getAuthParameter(ctx, auth.ClientID, kube, isClusterKind, namespace) - if err != nil { - return nil, err - } - privateKey, err := getAuthParameter(ctx, auth.PrivateKey, kube, isClusterKind, namespace) - if err != nil { - return nil, err - } - serverPublicKeyID, err := getAuthParameter(ctx, auth.ServerPublicKeyID, kube, isClusterKind, namespace) - if err != nil { - return nil, err - } - - return map[string]string{ - "appKey": apiKey, - "appOwnerPublicKey": appOwnerPublicKey, - "clientId": clientID, - "hostname": store.Hostname, - "privateKey": privateKey, - "serverPublicKeyID": serverPublicKeyID, - }, nil -} -func getAuthParameter(ctx context.Context, param smmeta.SecretKeySelector, kube kclient.Client, isClusterKind bool, namespace string) (string, error) { credentialsSecret := &v1.Secret{} - credentialsSecretName := param.Name + credentialsSecretName := auth.Name objectKey := types.NamespacedName{ Name: credentialsSecretName, Namespace: namespace, @@ -184,10 +131,10 @@ func getAuthParameter(ctx context.Context, param smmeta.SecretKeySelector, kube // only ClusterStore is allowed to set namespace (and then it's required) if isClusterKind { - if credentialsSecretName != "" && param.Namespace == nil { + if credentialsSecretName != "" && auth.Namespace == nil { return "", fmt.Errorf(errInvalidClusterStoreMissingK8sSecretNamespace) } else if credentialsSecretName != "" { - objectKey.Namespace = *param.Namespace + objectKey.Namespace = *auth.Namespace } } @@ -195,9 +142,9 @@ func getAuthParameter(ctx context.Context, param smmeta.SecretKeySelector, kube if err != nil { return "", fmt.Errorf(errFetchK8sSecret, err) } - data := credentialsSecret.Data[param.Key] + data := credentialsSecret.Data[auth.Key] if (data == nil) || (len(data) == 0) { - return "", fmt.Errorf(errMissingK8sSecretKey, param.Key) + return "", fmt.Errorf(errMissingK8sSecretKey, auth.Key) } return string(data), nil From 783440193363986801ccc563d6f6297520d33129 Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Tue, 28 Feb 2023 21:12:34 +0100 Subject: [PATCH 36/62] fix: docs build (#2068) Signed-off-by: Moritz Johner --- docs/api/generator/acr.md | 28 ++---------------- docs/api/spec.md | 2 +- docs/provider/keeper-security.md | 3 ++ docs/snippets/generator-acr-example.yaml | 29 +++++++++++++++++++ .../keepersecurity-external-secret.yaml | 2 ++ 5 files changed, 37 insertions(+), 27 deletions(-) create mode 100644 docs/snippets/generator-acr-example.yaml diff --git a/docs/api/generator/acr.md b/docs/api/generator/acr.md index 7bc18ab0c1a..3804e6381d1 100644 --- a/docs/api/generator/acr.md +++ b/docs/api/generator/acr.md @@ -47,31 +47,7 @@ repository:my-repository:pull {% include 'generator-acr.yaml' %} ``` +Example ExternalSecret that references the ACR generator: ```yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: azurecr-credentials -spec: - dataFrom: - - sourceRef: - generatorRef: - apiVersion: generators.external-secrets.io/v1alpha1 - kind: ACRAccessToken - name: myregistry.azurecr.io - refreshInterval: 12h - target: - name: azurecr-credentials - template: - type: kubernetes.io/dockerconfigjson - data: - .dockerconfigjson: | - { - "auths": { - "myregistry.azurecr.io": { - "username": "{{ .username }}", - "identitytoken": "{{ .password }}", - } - } - } +{% include 'generator-acr-example.yaml' %} ``` \ No newline at end of file diff --git a/docs/api/spec.md b/docs/api/spec.md index 922d18ec8d9..ad84a131275 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -5105,7 +5105,7 @@ External Secrets meta/v1.SecretKeySelector

Error indicates that there is a misconfiguration.

0

-

Ready indicates that the client is confgured correctly +

Ready indicates that the client is configured correctly and can be used.

1

diff --git a/docs/provider/keeper-security.md b/docs/provider/keeper-security.md index 74d47cec020..0627ec4cbc8 100644 --- a/docs/provider/keeper-security.md +++ b/docs/provider/keeper-security.md @@ -14,6 +14,7 @@ KSM can authenticate using *One Time Access Token* or *Secret Manager Configurat You can find the documentation for the Secret Manager Configuration creation [here](https://docs.keeper.io/secrets-manager/secrets-manager/about/secrets-manager-configuration). Make sure you add the proper permissions to your device in order to be able to read and write secrets Once you have created your SMC, you will get a config.json file or a base64 json encoded string containing the following keys: + - `hostname` - `clientId` - `privateKey` @@ -34,6 +35,7 @@ Be sure the `keepersecurity` provider is listed in the `Kind=SecretStore` ``` **NOTE 1:** `folderID` target the folder ID where the secrets should be pushed to. It requires write permissions within the folder + **NOTE 2:** In case of a `ClusterSecretStore`, Be sure to provide `namespace` for `SecretAccessKeyRef` with the namespace of the secret that we just created. ## External Secrets @@ -69,6 +71,7 @@ kubectl get secret secret-to-be-created -n | -o jsonpath='{.data.dev ## Limitations There are some limitations using this provider. + * Keeper Secret Manager does not work with `General` Records types nor legacy non-typed records * Using tags `find.tags` is not supported by KSM * Using path `find.path` is not supported at the moment diff --git a/docs/snippets/generator-acr-example.yaml b/docs/snippets/generator-acr-example.yaml new file mode 100644 index 00000000000..ce91ab80acd --- /dev/null +++ b/docs/snippets/generator-acr-example.yaml @@ -0,0 +1,29 @@ +{% raw %} + +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: azurecr-credentials +spec: + dataFrom: + - sourceRef: + generatorRef: + apiVersion: generators.external-secrets.io/v1alpha1 + kind: ACRAccessToken + name: myregistry.azurecr.io + refreshInterval: 12h + target: + name: azurecr-credentials + template: + type: kubernetes.io/dockerconfigjson + data: + .dockerconfigjson: | + { + "auths": { + "myregistry.azurecr.io": { + "username": "{{ .username }}", + "identitytoken": "{{ .password }}", + } + } + } +{% endraw %} diff --git a/docs/snippets/keepersecurity-external-secret.yaml b/docs/snippets/keepersecurity-external-secret.yaml index c68a002f10f..0db04c3f0b3 100644 --- a/docs/snippets/keepersecurity-external-secret.yaml +++ b/docs/snippets/keepersecurity-external-secret.yaml @@ -1,3 +1,4 @@ +{% raw %} apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: @@ -69,3 +70,4 @@ spec: remoteRef: key: OqPt3Vd37My7G8rTb-8Q property: password +{% endraw %} From c28707aa5298b9e410c51a3f3636cfb42aa39bc0 Mon Sep 17 00:00:00 2001 From: Shuhei Kitagawa Date: Fri, 3 Mar 2023 06:27:24 +0900 Subject: [PATCH 37/62] :sparkles: Support property in fake provider (#2056) * Support property in fake provider Signed-off-by: shuheiktgw * Remove a unused function Signed-off-by: shuheiktgw * fix autogen api/spec.md Signed-off-by: Moritz Johner --------- Signed-off-by: shuheiktgw Signed-off-by: Moritz Johner Co-authored-by: Moritz Johner --- pkg/provider/fake/fake.go | 11 +++++++++++ pkg/provider/fake/fake_test.go | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/pkg/provider/fake/fake.go b/pkg/provider/fake/fake.go index 506ea5a3ac4..b6b52de0afc 100644 --- a/pkg/provider/fake/fake.go +++ b/pkg/provider/fake/fake.go @@ -18,6 +18,7 @@ import ( "context" "fmt" + "github.com/tidwall/gjson" "sigs.k8s.io/controller-runtime/pkg/client" esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" @@ -134,6 +135,16 @@ func (p *Provider) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDa if !ok || data.Version != ref.Version { return nil, esv1beta1.NoSecretErr } + + if ref.Property != "" { + val := gjson.Get(data.Value, ref.Property) + if !val.Exists() { + return nil, esv1beta1.NoSecretErr + } + + return []byte(val.String()), nil + } + return []byte(data.Value), nil } diff --git a/pkg/provider/fake/fake_test.go b/pkg/provider/fake/fake_test.go index 676d0fd2725..f3ec5e4d6a3 100644 --- a/pkg/provider/fake/fake_test.go +++ b/pkg/provider/fake/fake_test.go @@ -124,6 +124,24 @@ func TestGetSecret(t *testing.T) { }, expValue: "bar2", }, + { + name: "get correct value from multiple properties", + input: []esv1beta1.FakeProviderData{ + { + Key: "junk", + Value: "xxxxx", + }, + { + Key: "/foo", + Value: `{"p1":"bar","p2":"bar2"}`, + }, + }, + request: esv1beta1.ExternalSecretDataRemoteRef{ + Key: "/foo", + Property: "p2", + }, + expValue: "bar2", + }, } for i, row := range tbl { From f44f366e05e1033da2231cfdb7704bf17384763a Mon Sep 17 00:00:00 2001 From: Pedro Parra Ortega Date: Thu, 2 Mar 2023 22:28:35 +0100 Subject: [PATCH 38/62] :broom: remove hostname from keeper configuration (#2071) * remove hostname from keeper configuration Signed-off-by: Pedro Parra Ortega --- .../v1beta1/secretstore_keepersecurity_types.go | 1 - .../bases/external-secrets.io_clustersecretstores.yaml | 3 --- .../crds/bases/external-secrets.io_secretstores.yaml | 3 --- deploy/crds/bundle.yaml | 6 ------ docs/api/spec.md | 10 ---------- docs/snippets/keepersecurity-secret-store.yaml | 1 - pkg/provider/keepersecurity/provider.go | 7 ------- 7 files changed, 31 deletions(-) diff --git a/apis/externalsecrets/v1beta1/secretstore_keepersecurity_types.go b/apis/externalsecrets/v1beta1/secretstore_keepersecurity_types.go index e3e85dedb77..749b6cf919b 100644 --- a/apis/externalsecrets/v1beta1/secretstore_keepersecurity_types.go +++ b/apis/externalsecrets/v1beta1/secretstore_keepersecurity_types.go @@ -19,6 +19,5 @@ import smmeta "github.com/external-secrets/external-secrets/apis/meta/v1" // KeeperSecurityProvider Configures a store to sync secrets using Keeper Security. type KeeperSecurityProvider struct { Auth smmeta.SecretKeySelector `json:"authRef"` - Hostname string `json:"hostname"` FolderID string `json:"folderID"` } diff --git a/config/crds/bases/external-secrets.io_clustersecretstores.yaml b/config/crds/bases/external-secrets.io_clustersecretstores.yaml index b23a3cde6cc..15b95136005 100644 --- a/config/crds/bases/external-secrets.io_clustersecretstores.yaml +++ b/config/crds/bases/external-secrets.io_clustersecretstores.yaml @@ -2388,12 +2388,9 @@ spec: type: object folderID: type: string - hostname: - type: string required: - authRef - folderID - - hostname type: object kubernetes: description: Kubernetes configures this store to sync secrets diff --git a/config/crds/bases/external-secrets.io_secretstores.yaml b/config/crds/bases/external-secrets.io_secretstores.yaml index 3633745f468..54ba2bf5492 100644 --- a/config/crds/bases/external-secrets.io_secretstores.yaml +++ b/config/crds/bases/external-secrets.io_secretstores.yaml @@ -2388,12 +2388,9 @@ spec: type: object folderID: type: string - hostname: - type: string required: - authRef - folderID - - hostname type: object kubernetes: description: Kubernetes configures this store to sync secrets diff --git a/deploy/crds/bundle.yaml b/deploy/crds/bundle.yaml index 8c7784e3233..c5575334855 100644 --- a/deploy/crds/bundle.yaml +++ b/deploy/crds/bundle.yaml @@ -2191,12 +2191,9 @@ spec: type: object folderID: type: string - hostname: - type: string required: - authRef - folderID - - hostname type: object kubernetes: description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider @@ -5509,12 +5506,9 @@ spec: type: object folderID: type: string - hostname: - type: string required: - authRef - folderID - - hostname type: object kubernetes: description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider diff --git a/docs/api/spec.md b/docs/api/spec.md index ad84a131275..61e53fccdf9 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -3456,16 +3456,6 @@ External Secrets meta/v1.SecretKeySelector -hostname
- -string - - - - - - - folderID
string diff --git a/docs/snippets/keepersecurity-secret-store.yaml b/docs/snippets/keepersecurity-secret-store.yaml index 0213ec63a54..9a1773f353f 100644 --- a/docs/snippets/keepersecurity-secret-store.yaml +++ b/docs/snippets/keepersecurity-secret-store.yaml @@ -6,7 +6,6 @@ metadata: spec: provider: keepersecurity: - hostname: keepersecurity.eu authRef: # Refer to a kubernetes secret which holds the base64 encoded json string for the configuration name: keeper-configuration key: auth diff --git a/pkg/provider/keepersecurity/provider.go b/pkg/provider/keepersecurity/provider.go index b4eb1e1e6f3..fc1b87fb5e1 100644 --- a/pkg/provider/keepersecurity/provider.go +++ b/pkg/provider/keepersecurity/provider.go @@ -16,7 +16,6 @@ package keepersecurity import ( "context" "fmt" - "net/url" ksm "github.com/keeper-security/secrets-manager-go/core" "github.com/keeper-security/secrets-manager-go/core/logger" @@ -36,7 +35,6 @@ const ( errKeeperSecurityNilSpecProviderKeeperSecurity = "nil spec.provider.keepersecurity" errKeeperSecurityStoreMissingAuth = "missing: spec.provider.keepersecurity.auth" errKeeperSecurityStoreMissingFolderID = "missing: spec.provider.keepersecurity.folderID" - errKeeperSecurityStoreInvalidConnectHost = "unable to parse URL: spec.provider.keepersecurity.connectHost: %w" errInvalidClusterStoreMissingK8sSecretNamespace = "invalid ClusterSecretStore: missing KeeperSecurity k8s Auth Secret Namespace" errFetchK8sSecret = "could not fetch k8s Secret: %w" errMissingK8sSecretKey = "missing Secret key: %s" @@ -104,11 +102,6 @@ func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error { // check mandatory fields config := spc.Provider.KeeperSecurity - // check valid URL - if _, err := url.Parse(config.Hostname); err != nil { - return fmt.Errorf(errKeeperSecurityStoreInvalidConnectHost, err) - } - if err := utils.ValidateSecretSelector(store, config.Auth); err != nil { return fmt.Errorf(errKeeperSecurityStoreMissingAuth) } From 043db7e08a285b08c3b8a01743a4efd19cb5444b Mon Sep 17 00:00:00 2001 From: Mubarak Jama <83465122+mubarak-j@users.noreply.github.com> Date: Thu, 2 Mar 2023 14:30:18 -0700 Subject: [PATCH 39/62] docs: fix auth secretRef in API docs (#2077) Signed-off-by: Mubarak Jama <83465122+mubarak-j@users.noreply.github.com> --- docs/snippets/full-secret-store.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/snippets/full-secret-store.yaml b/docs/snippets/full-secret-store.yaml index 3e9e387e365..4cf3cd43044 100644 --- a/docs/snippets/full-secret-store.yaml +++ b/docs/snippets/full-secret-store.yaml @@ -35,10 +35,10 @@ spec: # getting the accessKeyID and secretAccessKey from an already created Kubernetes Secret auth: secretRef: - accessKeyID: + accessKeyIDSecretRef: name: awssm-secret key: access-key - secretAccessKey: + secretAccessKeySecretRef: name: awssm-secret key: secret-access-key From 5b0ff977de1c709971be7e26572ee1d735494dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20G=C3=B3mez?= <1637983+sebagomez@users.noreply.github.com> Date: Mon, 6 Mar 2023 03:56:31 -0500 Subject: [PATCH 40/62] :sparkles: Included metadataPolicy: Fetch in Hashicorp Vault (#2040) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Implement fetch metadata from Hashicorp Vault (v2) Signed-off-by: Sebastián Gómez --- pkg/provider/vault/fake/vault.go | 14 ++++++ pkg/provider/vault/vault.go | 68 +++++++++++++++++---------- pkg/provider/vault/vault_test.go | 79 ++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 23 deletions(-) diff --git a/pkg/provider/vault/fake/vault.go b/pkg/provider/vault/fake/vault.go index 9b0369b1d9b..ad6587e815a 100644 --- a/pkg/provider/vault/fake/vault.go +++ b/pkg/provider/vault/fake/vault.go @@ -64,6 +64,20 @@ func NewReadWithContextFn(secret map[string]interface{}, err error) ReadWithData } } +func NewReadMetadataWithContextFn(secret map[string]interface{}, err error) ReadWithDataWithContextFn { + return func(ctx context.Context, path string, data map[string][]string) (*vault.Secret, error) { + if secret == nil { + return nil, err + } + metadata := make(map[string]interface{}) + metadata["custom_metadata"] = secret + vault := &vault.Secret{ + Data: metadata, + } + return vault, err + } +} + func NewWriteWithContextFn(secret map[string]interface{}, err error) WriteWithContextFn { return func(ctx context.Context, path string, data map[string]interface{}) (*vault.Secret, error) { vault := &vault.Secret{ diff --git a/pkg/provider/vault/vault.go b/pkg/provider/vault/vault.go index 69430ec06bd..8a4bca2e260 100644 --- a/pkg/provider/vault/vault.go +++ b/pkg/provider/vault/vault.go @@ -64,26 +64,27 @@ var ( const ( serviceAccTokenPath = "/var/run/secrets/kubernetes.io/serviceaccount/token" - errVaultStore = "received invalid Vault SecretStore resource: %w" - errVaultCacheCreate = "cannot create Vault client cache: %s" - errVaultCacheRemove = "error removing item from Vault client cache: %w" - errVaultCacheEviction = "unexpected eviction from Vault client cache" - errVaultClient = "cannot setup new vault client: %w" - errVaultCert = "cannot set Vault CA certificate: %w" - errReadSecret = "cannot read secret data from Vault: %w" - errAuthFormat = "cannot initialize Vault client: no valid auth method specified" - errInvalidCredentials = "invalid vault credentials: %w" - errDataField = "failed to find data field" - errJSONUnmarshall = "failed to unmarshall JSON" - errPathInvalid = "provided Path isn't a valid kv v2 path" - errSecretFormat = "secret data not in expected format" - errUnexpectedKey = "unexpected key in data: %s" - errVaultToken = "cannot parse Vault authentication token: %w" - errVaultRequest = "error from Vault request: %w" - errServiceAccount = "cannot read Kubernetes service account token from file system: %w" - errJwtNoTokenSource = "neither `secretRef` nor `kubernetesServiceAccountToken` was supplied as token source for jwt authentication" - errUnsupportedKvVersion = "cannot perform find operations with kv version v1" - errNotFound = "secret not found" + errVaultStore = "received invalid Vault SecretStore resource: %w" + errVaultCacheCreate = "cannot create Vault client cache: %s" + errVaultCacheRemove = "error removing item from Vault client cache: %w" + errVaultCacheEviction = "unexpected eviction from Vault client cache" + errVaultClient = "cannot setup new vault client: %w" + errVaultCert = "cannot set Vault CA certificate: %w" + errReadSecret = "cannot read secret data from Vault: %w" + errAuthFormat = "cannot initialize Vault client: no valid auth method specified" + errInvalidCredentials = "invalid vault credentials: %w" + errDataField = "failed to find data field" + errJSONUnmarshall = "failed to unmarshall JSON" + errPathInvalid = "provided Path isn't a valid kv v2 path" + errSecretFormat = "secret data not in expected format" + errUnexpectedKey = "unexpected key in data: %s" + errVaultToken = "cannot parse Vault authentication token: %w" + errVaultRequest = "error from Vault request: %w" + errServiceAccount = "cannot read Kubernetes service account token from file system: %w" + errJwtNoTokenSource = "neither `secretRef` nor `kubernetesServiceAccountToken` was supplied as token source for jwt authentication" + errUnsupportedKvVersion = "cannot perform find operations with kv version v1" + errUnsupportedMetadataKvVersion = "cannot perform metadata fetch operations with kv version v1" + errNotFound = "secret not found" errGetKubeSA = "cannot get Kubernetes service account %q: %w" errGetKubeSASecrets = "cannot find secrets bound to service account: %q" @@ -626,10 +627,31 @@ func (v *client) readSecretMetadata(ctx context.Context, path string) (map[strin // 2. get a key from the secret. // Nested values are supported by specifying a gjson expression func (v *client) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) { - data, err := v.readSecret(ctx, ref.Key, ref.Version) - if err != nil { - return nil, err + var data map[string]interface{} + var err error + if ref.MetadataPolicy == esv1beta1.ExternalSecretMetadataPolicyFetch { + if v.store.Version == esv1beta1.VaultKVStoreV1 { + return nil, errors.New(errUnsupportedMetadataKvVersion) + } + + metadata, err := v.readSecretMetadata(ctx, ref.Key) + if err != nil { + return nil, err + } + if len(metadata) == 0 { + return nil, nil + } + data = make(map[string]interface{}, len(metadata)) + for k, v := range metadata { + data[k] = v + } + } else { + data, err = v.readSecret(ctx, ref.Key, ref.Version) + if err != nil { + return nil, err + } } + // Return nil if secret value is null if data == nil { return nil, nil diff --git a/pkg/provider/vault/vault_test.go b/pkg/provider/vault/vault_test.go index 32c61a41a45..28e0bc03d88 100644 --- a/pkg/provider/vault/vault_test.go +++ b/pkg/provider/vault/vault_test.go @@ -630,6 +630,85 @@ func TestGetSecret(t *testing.T) { err: esv1beta1.NoSecretError{}, }, }, + "ReadSecretMetadataWithoutProperty": { + reason: "Should return the json encoded metadata", + args: args{ + store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault, + data: esv1beta1.ExternalSecretDataRemoteRef{ + MetadataPolicy: "Fetch", + }, + vLogical: &fake.Logical{ + ReadWithDataWithContextFn: fake.NewReadMetadataWithContextFn(secret, nil), + }, + }, + want: want{ + err: nil, + val: []byte(`{"access_key":"access_key","access_secret":"access_secret"}`), + }, + }, + "ReadSecretMetadataWithProperty": { + reason: "Should return the access_key value from the metadata", + args: args{ + store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault, + data: esv1beta1.ExternalSecretDataRemoteRef{ + MetadataPolicy: "Fetch", + Property: "access_key", + }, + vLogical: &fake.Logical{ + ReadWithDataWithContextFn: fake.NewReadMetadataWithContextFn(secret, nil), + }, + }, + want: want{ + err: nil, + val: []byte("access_key"), + }, + }, + "FailReadSecretMetadataInvalidProperty": { + reason: "Should return error of non existent key inmetadata", + args: args{ + store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault, + data: esv1beta1.ExternalSecretDataRemoteRef{ + MetadataPolicy: "Fetch", + Property: "does_not_exist", + }, + vLogical: &fake.Logical{ + ReadWithDataWithContextFn: fake.NewReadMetadataWithContextFn(secret, nil), + }, + }, + want: want{ + err: fmt.Errorf(errSecretKeyFmt, "does_not_exist"), + }, + }, + "FailReadSecretMetadataNoMetadata": { + reason: "Should return the access_key value from the metadata", + args: args{ + store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault, + data: esv1beta1.ExternalSecretDataRemoteRef{ + MetadataPolicy: "Fetch", + }, + vLogical: &fake.Logical{ + ReadWithDataWithContextFn: fake.NewReadMetadataWithContextFn(nil, nil), + }, + }, + want: want{ + err: fmt.Errorf(errNotFound), + }, + }, + "FailReadSecretMetadataWrongVersion": { + reason: "Should return the access_key value from the metadata", + args: args{ + store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV1).Spec.Provider.Vault, + data: esv1beta1.ExternalSecretDataRemoteRef{ + MetadataPolicy: "Fetch", + }, + vLogical: &fake.Logical{ + ReadWithDataWithContextFn: fake.NewReadMetadataWithContextFn(nil, nil), + }, + }, + want: want{ + err: fmt.Errorf(errUnsupportedMetadataKvVersion), + }, + }, } for name, tc := range cases { From bdd5899ac61ed0c6b7027d1b12e389b367726d46 Mon Sep 17 00:00:00 2001 From: Steve Mitchell Date: Mon, 6 Mar 2023 05:44:02 -0500 Subject: [PATCH 41/62] go.mod dependency cleanup (#2085) * deps: remove awkward k8s.io/client-go version PR #1525 accidentally assumed that k8s.io/client-go followed semvar and update the lib to the latest 1.x release. Unfortunately, that project doesn't follow semvar on major versions so this actually _downgraded_ the package to one ~15 months earlier. This was subsequently fixed with replace statements but the go mod file is easier to reason about if we correct this Signed-off-by: Steve Mitchell * deps: remove unncessary replace statements PR #1990 attempted to bump the version of some dependencies but missed the versions being set in the replace statements. This caused some of the deps to not actually get updated (as can be seen by the contents of the go.sum file). It turns out most of these replace statements are for libraries that aren't currently being imported, so I cleaned up the whole block. The resulting changes can be seen in the go.sum file Signed-off-by: Steve Mitchell --------- Signed-off-by: Steve Mitchell --- go.mod | 32 +------------------------------- go.sum | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 41 deletions(-) diff --git a/go.mod b/go.mod index 1e14ffb7066..c2ded745bd1 100644 --- a/go.mod +++ b/go.mod @@ -2,36 +2,6 @@ module github.com/external-secrets/external-secrets go 1.19 -replace ( - github.com/go-check/check => github.com/go-check/check v0.0.0-20180628173108-788fd7840127 - github.com/go-test/deep => github.com/go-test/deep v1.0.4 - k8s.io/api => k8s.io/api v0.26.0 - k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.26.0 - k8s.io/apimachinery => k8s.io/apimachinery v0.26.0 - k8s.io/apiserver => k8s.io/apiserver v0.26.0 - k8s.io/cli-runtime => k8s.io/cli-runtime v0.26.0 - k8s.io/client-go => k8s.io/client-go v0.26.0 - k8s.io/cloud-provider => k8s.io/cloud-provider v0.26.0 - k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.26.0 - k8s.io/code-generator => k8s.io/code-generator v0.26.0 - k8s.io/component-base => k8s.io/component-base v0.26.0 - k8s.io/component-helpers => k8s.io/component-helpers v0.26.0 - k8s.io/controller-manager => k8s.io/controller-manager v0.26.0 - k8s.io/cri-api => k8s.io/cri-api v0.26.0 - k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.26.0 - k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.26.0 - k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.26.0 - k8s.io/kube-proxy => k8s.io/kube-proxy v0.26.0 - k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.26.0 - k8s.io/kubectl => k8s.io/kubectl v0.26.0 - k8s.io/kubelet => k8s.io/kubelet v0.26.0 - k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.26.0 - k8s.io/metrics => k8s.io/metrics v0.26.0 - k8s.io/mount-utils => k8s.io/mount-utils v0.26.0 - k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.26.0 - k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.26.0 -) - require ( cloud.google.com/go/iam v0.12.0 cloud.google.com/go/secretmanager v1.10.0 @@ -84,7 +54,7 @@ require ( k8s.io/api v0.26.1 k8s.io/apiextensions-apiserver v0.26.1 k8s.io/apimachinery v0.26.1 - k8s.io/client-go v1.5.2 + k8s.io/client-go v0.26.1 k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 sigs.k8s.io/controller-runtime v0.14.4 sigs.k8s.io/controller-tools v0.11.3 diff --git a/go.sum b/go.sum index fb75e3e261d..5c3b3b0001f 100644 --- a/go.sum +++ b/go.sum @@ -217,6 +217,7 @@ github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyh github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA= @@ -1025,16 +1026,16 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.26.0 h1:IpPlZnxBpV1xl7TGk/X6lFtpgjgntCg8PJ+qrPHAC7I= -k8s.io/api v0.26.0/go.mod h1:k6HDTaIFC8yn1i6pSClSqIwLABIcLV9l5Q4EcngKnQg= -k8s.io/apiextensions-apiserver v0.26.0 h1:Gy93Xo1eg2ZIkNX/8vy5xviVSxwQulsnUdQ00nEdpDo= -k8s.io/apiextensions-apiserver v0.26.0/go.mod h1:7ez0LTiyW5nq3vADtK6C3kMESxadD51Bh6uz3JOlqWQ= -k8s.io/apimachinery v0.26.0 h1:1feANjElT7MvPqp0JT6F3Ss6TWDwmcjLypwoPpEf7zg= -k8s.io/apimachinery v0.26.0/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= -k8s.io/client-go v0.26.0 h1:lT1D3OfO+wIi9UFolCrifbjUUgu7CpLca0AD8ghRLI8= -k8s.io/client-go v0.26.0/go.mod h1:I2Sh57A79EQsDmn7F7ASpmru1cceh3ocVT9KlX2jEZg= -k8s.io/component-base v0.26.0 h1:0IkChOCohtDHttmKuz+EP3j3+qKmV55rM9gIFTXA7Vs= -k8s.io/component-base v0.26.0/go.mod h1:lqHwlfV1/haa14F/Z5Zizk5QmzaVf23nQzCwVOQpfC8= +k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= +k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= +k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= +k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= +k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ= +k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= +k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= +k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= +k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4= +k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU= k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9 h1:iu3o/SxaHVI7tKPtkGzD3M9IzrE21j+CUKH98NQJ8Ms= k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= From d3213d13c23b7f6fd6a724a7d1ce315f491dbfa6 Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Mon, 6 Mar 2023 12:57:08 +0100 Subject: [PATCH 42/62] chore: bump deps (#2098) Signed-off-by: Moritz Johner --- e2e/go.mod | 44 +++++++++--------- e2e/go.sum | 71 ++++++++++++++--------------- go.mod | 62 ++++++++++++------------- go.sum | 129 +++++++++++++++++++++++++++-------------------------- 4 files changed, 154 insertions(+), 152 deletions(-) diff --git a/e2e/go.mod b/e2e/go.mod index 9806b557aa1..a0b9969b6a1 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -43,27 +43,27 @@ require ( github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 github.com/akeylesslabs/akeyless-go/v2 v2.20.3 - github.com/aliyun/alibaba-cloud-sdk-go v1.62.192 + github.com/aliyun/alibaba-cloud-sdk-go v1.62.217 github.com/argoproj/argo-cd/v2 v2.4.8 - github.com/aws/aws-sdk-go v1.44.209 + github.com/aws/aws-sdk-go v1.44.214 github.com/external-secrets/external-secrets v0.0.0 github.com/fluxcd/helm-controller/api v0.22.2 github.com/fluxcd/pkg/apis/meta v0.14.2 github.com/fluxcd/source-controller/api v0.25.11 github.com/golang-jwt/jwt/v4 v4.5.0 github.com/hashicorp/vault/api v1.9.0 - github.com/onsi/ginkgo/v2 v2.8.3 + github.com/onsi/ginkgo/v2 v2.9.0 github.com/onsi/gomega v1.27.1 github.com/oracle/oci-go-sdk/v56 v56.1.0 github.com/xanzy/go-gitlab v0.80.2 - golang.org/x/oauth2 v0.5.0 - google.golang.org/api v0.110.0 - k8s.io/api v0.26.1 - k8s.io/apiextensions-apiserver v0.26.1 - k8s.io/apimachinery v0.26.1 + golang.org/x/oauth2 v0.6.0 + google.golang.org/api v0.111.0 + k8s.io/api v0.26.2 + k8s.io/apiextensions-apiserver v0.26.2 + k8s.io/apimachinery v0.26.2 k8s.io/client-go v1.5.2 k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 - sigs.k8s.io/controller-runtime v0.14.4 + sigs.k8s.io/controller-runtime v0.14.5 software.sslmate.com/src/go-pkcs12 v0.2.0 ) @@ -129,7 +129,7 @@ require ( github.com/google/go-github/v41 v41.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20230222194610-99052d3372e7 // indirect + github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect @@ -175,7 +175,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.40.0 // indirect + github.com/prometheus/common v0.41.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/robfig/cron v1.2.0 // indirect github.com/russross/blackfriday v1.5.2 // indirect @@ -185,7 +185,7 @@ require ( github.com/sony/gobreaker v0.5.0 // indirect github.com/spf13/cobra v1.6.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/testify v1.8.1 // indirect + github.com/stretchr/testify v1.8.2 // indirect github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect @@ -196,18 +196,18 @@ require ( github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect go.opencensus.io v0.24.0 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect - golang.org/x/crypto v0.6.0 // indirect - golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect - golang.org/x/net v0.7.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/exp v0.0.0-20230304125523-9ff063c70017 // indirect + golang.org/x/net v0.8.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/term v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.6.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 // indirect + google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 // indirect google.golang.org/grpc v1.53.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect @@ -219,11 +219,11 @@ require ( grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 // indirect k8s.io/apiserver v0.24.2 // indirect k8s.io/cli-runtime v0.24.2 // indirect - k8s.io/component-base v0.26.1 // indirect + k8s.io/component-base v0.26.2 // indirect k8s.io/component-helpers v0.24.2 // indirect - k8s.io/klog/v2 v2.90.0 // indirect + k8s.io/klog/v2 v2.90.1 // indirect k8s.io/kube-aggregator v0.24.2 // indirect - k8s.io/kube-openapi v0.0.0-20230224204730-66828de6f33b // indirect + k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d // indirect k8s.io/kubectl v0.24.2 // indirect k8s.io/kubernetes v1.24.2 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/e2e/go.sum b/e2e/go.sum index 24fc66ae865..937331d9e32 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -20,7 +20,7 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.107.0 h1:qkj22L7bgkl6vIeZDlOY2po43Mx/TIa2Wsa7VR+PEww= +cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -36,7 +36,7 @@ cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1 cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/iam v0.12.0 h1:DRtTY29b75ciH6Ov1PHb4/iat2CLCvrOm40Q0a6DFpE= cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= -cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= +cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -125,8 +125,8 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI= github.com/alicebob/miniredis/v2 v2.14.2 h1:VeoqKUAsJfT2af61nDE7qhBzqn3J6xjnt9MFAbdrEtg= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.192 h1:tsF4NZgpWu/2vxTKJUTpg24UxLlkzmox3ezOqPZGcr8= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.192/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.217 h1:YZPv3FMTEP9s5u547eY3E+7s8FothzjWvITtqwhljSE= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.217/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -154,8 +154,8 @@ github.com/aws/aws-sdk-go v1.33.16/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZve github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= github.com/aws/aws-sdk-go v1.38.49/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.44.209 h1:wZuiaA4eaqYZmoZXqGgNHqVD7y7kUGFvACDGBgowTps= -github.com/aws/aws-sdk-go v1.44.209/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.214 h1:YzDuC+9UtrAOUkItlK7l3BvKI9o6qAog9X8i289HORc= +github.com/aws/aws-sdk-go v1.44.214/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -484,8 +484,8 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230222194610-99052d3372e7 h1:pNFnpaSXfibgW7aUbk9pwLmI7LNwh/iR46x/YwN/lNg= -github.com/google/pprof v0.0.0-20230222194610-99052d3372e7/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= +github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 h1:CqYfpuYIjnlNxM3msdyPRKabhXZWbKjf3Q8BWROFBso= +github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -742,8 +742,8 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.8.3 h1:RpbK1G8nWPNaCVFBWsOGnEQQGgASi6b8fxcWBvDYjxQ= -github.com/onsi/ginkgo/v2 v2.8.3/go.mod h1:6OaUA8BCi0aZfmzYT/q9AacwTzDpNbxILUT+TlBq6MY= +github.com/onsi/ginkgo/v2 v2.9.0 h1:Tugw2BKlNHTMfG+CheOITkYvk4LAh6MFOvikhGVnhE8= +github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= @@ -821,8 +821,8 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.40.0 h1:Afz7EVRqGg2Mqqf4JuF9vdvp1pi220m55Pi9T2JnO4Q= -github.com/prometheus/common v0.40.0/go.mod h1:L65ZJPSmfn/UBWLQIHV7dBrKFidB/wPlF1y5TlSt9OE= +github.com/prometheus/common v0.41.0 h1:npo01n6vUlRViIj5fgwiK8vlNIh8bnoxqh3gypKsyAw= +github.com/prometheus/common v0.41.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -922,8 +922,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= @@ -1055,8 +1056,8 @@ golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1074,8 +1075,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20210220032938-85be41e4509f/go.mod h1:I6l2HNBLBZEcrOoCpyKLdY2lHoRZ8lI4x60KMCQDft4= golang.org/x/exp v0.0.0-20210901193431-a062eea981d2/go.mod h1:a3o/VtDNHN+dCVLEpzjjUHOzR+Ln3DHX056ZPzoZGGA= -golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI= -golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230304125523-9ff063c70017 h1:3Ea9SZLCB0aRIhSEjM+iaGIlzzeDJdpi579El/YIhEE= +golang.org/x/exp v0.0.0-20230304125523-9ff063c70017/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1168,8 +1169,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1186,8 +1187,8 @@ golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= +golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1291,13 +1292,13 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1308,8 +1309,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1425,8 +1426,8 @@ google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.45.0/go.mod h1:ISLIJCedJolbZvDfAk+Ctuq5hf+aJ33WgtUsfyFoLXA= google.golang.org/api v0.46.0/go.mod h1:ceL4oozhkAiTID8XMmJBsIxID/9wMXJVVFXPg4ylg3I= -google.golang.org/api v0.110.0 h1:l+rh0KYUooe9JGbGVx71tbFo4SMbMTXK3I3ia2QSEeU= -google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= +google.golang.org/api v0.111.0 h1:bwKi+z2BsdwYFRKrqwutM+axAlYLz83gt5pDSXCJT+0= +google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1486,8 +1487,8 @@ google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 h1:znp6mq/drrY+6khTAlJUDNFFcDGV2ENLYKpMq8SyCds= -google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 h1:QQF+HdiI4iocoxUjjpLgvTYDHKm99C/VtTBFnfiCJos= +google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1622,15 +1623,15 @@ k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.5.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.90.0 h1:VkTxIV/FjRXn1fgNNcKGM8cfmL1Z33ZjXRTVxKCoF5M= -k8s.io/klog/v2 v2.90.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= +k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-aggregator v0.24.2 h1:vaKw45vFA5fIT0wdSehPIL7idjVxgLqz6iedOHedLG4= k8s.io/kube-aggregator v0.24.2/go.mod h1:Ju2jNDixn+vqeeKEBfjfpc204bO1pbdXX0N9knCxeMQ= k8s.io/kube-controller-manager v0.24.2/go.mod h1:KDE0yqiEvxYiO0WRpPA4rVx8AcK1vsWydUF37AJ9lTI= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kube-openapi v0.0.0-20230224204730-66828de6f33b h1:4dkmFEDQj0ZBLKCxJ0R+qzhvZmEvRdRaaZAE06tR/Lg= -k8s.io/kube-openapi v0.0.0-20230224204730-66828de6f33b/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY= +k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d h1:VcFq5n7wCJB2FQMCIHfC+f+jNcGgNMar1uKd6rVlifU= +k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY= k8s.io/kube-proxy v0.24.2/go.mod h1:bozS2ufl/Ns6s40Ue34eV7rqyLVygi5usSmCgW7rFU8= k8s.io/kube-scheduler v0.24.2/go.mod h1:DRa+aeXKSYUUOHHIc/9EcaO9+FW5FydaOfPSvaSW5Ko= k8s.io/kubectl v0.24.2 h1:+RfQVhth8akUmIc2Ge8krMl/pt66V7210ka3RE/p0J4= diff --git a/go.mod b/go.mod index c2ded745bd1..efff732a7fc 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/Azure/go-autorest/autorest/adal v0.9.22 github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 - github.com/IBM/go-sdk-core/v5 v5.13.0 + github.com/IBM/go-sdk-core/v5 v5.13.1 github.com/IBM/secrets-manager-go-sdk v1.0.49 github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/sprig/v3 v3.2.3 @@ -18,8 +18,8 @@ require ( github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 github.com/akeylesslabs/akeyless-go/v2 v2.20.3 - github.com/aliyun/alibaba-cloud-sdk-go v1.62.192 - github.com/aws/aws-sdk-go v1.44.209 + github.com/aliyun/alibaba-cloud-sdk-go v1.62.217 + github.com/aws/aws-sdk-go v1.44.214 github.com/go-logr/logr v1.2.3 github.com/go-test/deep v1.0.4 // indirect github.com/google/go-cmp v0.5.9 @@ -31,39 +31,39 @@ require ( github.com/hashicorp/vault/api/auth/ldap v0.4.0 github.com/huandu/xstrings v1.4.0 // indirect github.com/lestrrat-go/jwx v1.2.25 - github.com/onsi/ginkgo/v2 v2.8.3 + github.com/onsi/ginkgo/v2 v2.9.0 github.com/onsi/gomega v1.27.1 github.com/oracle/oci-go-sdk/v56 v56.1.0 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 github.com/spf13/cobra v1.6.1 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.8.2 github.com/tidwall/gjson v1.14.4 github.com/xanzy/go-gitlab v0.80.2 - github.com/yandex-cloud/go-genproto v0.0.0-20230220085534-5bd8ccb5865a - github.com/yandex-cloud/go-sdk v0.0.0-20230213085834-eedd655a7e14 + github.com/yandex-cloud/go-genproto v0.0.0-20230227093831-780473185775 + github.com/yandex-cloud/go-sdk v0.0.0-20230227095001-b676d5d7bc73 github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a go.uber.org/zap v1.24.0 - golang.org/x/crypto v0.6.0 - golang.org/x/oauth2 v0.5.0 - google.golang.org/api v0.110.0 - google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 // indirect + golang.org/x/crypto v0.7.0 + golang.org/x/oauth2 v0.6.0 + google.golang.org/api v0.111.0 + google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 // indirect google.golang.org/grpc v1.53.0 gopkg.in/yaml.v3 v3.0.1 grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 - k8s.io/api v0.26.1 - k8s.io/apiextensions-apiserver v0.26.1 - k8s.io/apimachinery v0.26.1 - k8s.io/client-go v0.26.1 + k8s.io/api v0.26.2 + k8s.io/apiextensions-apiserver v0.26.2 + k8s.io/apimachinery v0.26.2 + k8s.io/client-go v0.26.2 k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 - sigs.k8s.io/controller-runtime v0.14.4 + sigs.k8s.io/controller-runtime v0.14.5 sigs.k8s.io/controller-tools v0.11.3 ) require github.com/1Password/connect-sdk-go v1.5.0 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 github.com/hashicorp/golang-lru v0.5.4 github.com/keeper-security/secrets-manager-go/core v1.5.0 @@ -81,7 +81,7 @@ require ( require ( cloud.google.com/go/compute v1.18.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect @@ -91,7 +91,7 @@ require ( github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/Masterminds/semver/v3 v3.2.0 // indirect github.com/PaesslerAG/gval v1.2.2 // indirect - github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v3 v3.2.2 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect @@ -122,7 +122,7 @@ require ( github.com/google/gnostic v0.6.9 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20230222194610-99052d3372e7 // indirect + github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -140,7 +140,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/leodido/go-urn v1.2.1 // indirect + github.com/leodido/go-urn v1.2.2 // indirect github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect github.com/lestrrat-go/blackmagic v1.0.1 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect @@ -163,7 +163,7 @@ require ( github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/common v0.40.0 // indirect + github.com/prometheus/common v0.41.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect @@ -178,12 +178,12 @@ require ( go.opencensus.io v0.24.0 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 - golang.org/x/mod v0.8.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/exp v0.0.0-20230304125523-9ff063c70017 + golang.org/x/mod v0.9.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/term v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.6.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect @@ -193,11 +193,11 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/component-base v0.26.1 // indirect + k8s.io/component-base v0.26.2 // indirect k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9 // indirect k8s.io/klog v1.0.0 // indirect - k8s.io/klog/v2 v2.90.0 // indirect - k8s.io/kube-openapi v0.0.0-20230224204730-66828de6f33b // indirect + k8s.io/klog/v2 v2.90.1 // indirect + k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/go.sum b/go.sum index 5c3b3b0001f..d9d0f491f3e 100644 --- a/go.sum +++ b/go.sum @@ -18,7 +18,7 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.107.0 h1:qkj22L7bgkl6vIeZDlOY2po43Mx/TIa2Wsa7VR+PEww= +cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -33,7 +33,7 @@ cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7 cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/iam v0.12.0 h1:DRtTY29b75ciH6Ov1PHb4/iat2CLCvrOm40Q0a6DFpE= cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= -cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= +cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -50,12 +50,12 @@ github.com/1Password/connect-sdk-go v1.5.0 h1:F0WJcLSzGg3iXEDY49/ULdszYKsQLGTzn+ github.com/1Password/connect-sdk-go v1.5.0/go.mod h1:TdynFeyvaRoackENbJ8RfJokH+WAowAu1MLmUbdMq6s= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 h1:gVXuXcWd1i4C2Ruxe321aU+IKGaStvGB/S90PUPB/W8= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 h1:rTnT/Jrcm+figWlYz4Ixzt0SJVR2cMC8lvZcimipiEY= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 h1:+5VZ72z0Qan5Bog5C+ZkgSqUbeVUd9wgtHOrIKuc5b8= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= @@ -88,8 +88,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= -github.com/IBM/go-sdk-core/v5 v5.13.0 h1:foXLa2LfTSr3kgldpizaSDXH3gS/HB3YKj1BK8ywrE4= -github.com/IBM/go-sdk-core/v5 v5.13.0/go.mod h1:pVkN7IGmsSdmR1ZCU4E/cLcCclqRKMYgg7ya+O2Mk6g= +github.com/IBM/go-sdk-core/v5 v5.13.1 h1:zD6p3t1whAlRJo/VBmE69c8RcH9LCHL1n0/sO1MWlpw= +github.com/IBM/go-sdk-core/v5 v5.13.1/go.mod h1:pVkN7IGmsSdmR1ZCU4E/cLcCclqRKMYgg7ya+O2Mk6g= github.com/IBM/secrets-manager-go-sdk v1.0.49 h1:wRxyjFpSoZz6brj55JSMk6Sb38dLrQYnsEKcdYibflo= github.com/IBM/secrets-manager-go-sdk v1.0.49/go.mod h1:QyDSznC6gJEXIGaj+JPxoEVtyXfkaxzId87mxcEb+vM= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -112,16 +112,16 @@ github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 h1:vTckjyBhHOBiOWSC/oaEU2Oo4 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4/go.mod h1:As/RomC2w/fa3y+yHRlVHPmkbP+zrKBFRow41y5dk+E= github.com/akeylesslabs/akeyless-go/v2 v2.20.3 h1:NIRMynmpQbfgQyRLf5DMQC8p5iLgaUu1MXBB4ijLCxM= github.com/akeylesslabs/akeyless-go/v2 v2.20.3/go.mod h1:uOdXD49NCCe4rexeSc2aBU5Qv4KZgJE6YlbtYalvb+I= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.192 h1:tsF4NZgpWu/2vxTKJUTpg24UxLlkzmox3ezOqPZGcr8= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.192/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.217 h1:YZPv3FMTEP9s5u547eY3E+7s8FothzjWvITtqwhljSE= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.217/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.44.209 h1:wZuiaA4eaqYZmoZXqGgNHqVD7y7kUGFvACDGBgowTps= -github.com/aws/aws-sdk-go v1.44.209/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.214 h1:YzDuC+9UtrAOUkItlK7l3BvKI9o6qAog9X8i289HORc= +github.com/aws/aws-sdk-go v1.44.214/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -305,8 +305,8 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230222194610-99052d3372e7 h1:pNFnpaSXfibgW7aUbk9pwLmI7LNwh/iR46x/YwN/lNg= -github.com/google/pprof v0.0.0-20230222194610-99052d3372e7/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= +github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 h1:CqYfpuYIjnlNxM3msdyPRKabhXZWbKjf3Q8BWROFBso= +github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -400,8 +400,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= -github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/leodido/go-urn v1.2.2 h1:7z68G0FCGvDk646jz1AelTYNYWrTNm0bEcFAo147wt4= +github.com/leodido/go-urn v1.2.2/go.mod h1:kUaIbLZWttglzwNuG0pgsh5vuV6u2YcGBYz1hIPjtOQ= github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A= github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y= github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ= @@ -469,8 +469,8 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.8.3 h1:RpbK1G8nWPNaCVFBWsOGnEQQGgASi6b8fxcWBvDYjxQ= -github.com/onsi/ginkgo/v2 v2.8.3/go.mod h1:6OaUA8BCi0aZfmzYT/q9AacwTzDpNbxILUT+TlBq6MY= +github.com/onsi/ginkgo/v2 v2.9.0 h1:Tugw2BKlNHTMfG+CheOITkYvk4LAh6MFOvikhGVnhE8= +github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk= github.com/onsi/gomega v1.27.1 h1:rfztXRbg6nv/5f+Raen9RcGoSecHIFgBBLQK3Wdj754= github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfadcIAw= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= @@ -491,8 +491,8 @@ github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQg github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.40.0 h1:Afz7EVRqGg2Mqqf4JuF9vdvp1pi220m55Pi9T2JnO4Q= -github.com/prometheus/common v0.40.0/go.mod h1:L65ZJPSmfn/UBWLQIHV7dBrKFidB/wPlF1y5TlSt9OE= +github.com/prometheus/common v0.41.0 h1:npo01n6vUlRViIj5fgwiK8vlNIh8bnoxqh3gypKsyAw= +github.com/prometheus/common v0.41.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -502,6 +502,7 @@ github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/f github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/rwtodd/Go.Sed v0.0.0-20210816025313-55464686f9ef/go.mod h1:8AEUvGVi2uQ5b24BIhcr0GCcpd/RNAFWaN2CJFrWIIQ= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= @@ -537,8 +538,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -559,11 +561,10 @@ github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgk github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/yandex-cloud/go-genproto v0.0.0-20230213085250-850b3568e0c5/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= -github.com/yandex-cloud/go-genproto v0.0.0-20230220085534-5bd8ccb5865a h1:B0DLopiKFTX1y6rTHPRALhad4TP3dSAW0aTMTb5qSoU= -github.com/yandex-cloud/go-genproto v0.0.0-20230220085534-5bd8ccb5865a/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= -github.com/yandex-cloud/go-sdk v0.0.0-20230213085834-eedd655a7e14 h1:2yNVc+wIhp8SwyXdmbxGl7vT47oJWYxYxmRzReUelZM= -github.com/yandex-cloud/go-sdk v0.0.0-20230213085834-eedd655a7e14/go.mod h1:iICjK1Tf7LbahA6tJJ4akCHKnTjeGP+ceQKsjtWOiyo= +github.com/yandex-cloud/go-genproto v0.0.0-20230227093831-780473185775 h1:UdzHYFFZjQ2CqozbzHiddhvCNc9J8GN83jQqsC7K3VM= +github.com/yandex-cloud/go-genproto v0.0.0-20230227093831-780473185775/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= +github.com/yandex-cloud/go-sdk v0.0.0-20230227095001-b676d5d7bc73 h1:z0JIWqWBOt1Ue4tvgIrKa22KMY+IVtaM/bM2vGJrIA8= +github.com/yandex-cloud/go-sdk v0.0.0-20230227095001-b676d5d7bc73/go.mod h1:JtxzmSeRZaGwxGICpHE2U7Fl+EFHWKobm4HkeVUA2e0= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= @@ -610,8 +611,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -625,8 +626,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI= -golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230304125523-9ff063c70017 h1:3Ea9SZLCB0aRIhSEjM+iaGIlzzeDJdpi579El/YIhEE= +golang.org/x/exp v0.0.0-20230304125523-9ff063c70017/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -652,8 +653,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -695,8 +696,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -709,8 +710,8 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= +golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -779,15 +780,15 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -799,8 +800,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -894,8 +895,8 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.45.0/go.mod h1:ISLIJCedJolbZvDfAk+Ctuq5hf+aJ33WgtUsfyFoLXA= -google.golang.org/api v0.110.0 h1:l+rh0KYUooe9JGbGVx71tbFo4SMbMTXK3I3ia2QSEeU= -google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= +google.golang.org/api v0.111.0 h1:bwKi+z2BsdwYFRKrqwutM+axAlYLz83gt5pDSXCJT+0= +google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -947,8 +948,8 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 h1:znp6mq/drrY+6khTAlJUDNFFcDGV2ENLYKpMq8SyCds= -google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 h1:QQF+HdiI4iocoxUjjpLgvTYDHKm99C/VtTBFnfiCJos= +google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1026,16 +1027,16 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= -k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= -k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= -k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= -k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ= -k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= -k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= -k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= -k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4= -k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU= +k8s.io/api v0.26.2 h1:dM3cinp3PGB6asOySalOZxEG4CZ0IAdJsrYZXE/ovGQ= +k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU= +k8s.io/apiextensions-apiserver v0.26.2 h1:/yTG2B9jGY2Q70iGskMf41qTLhL9XeNN2KhI0uDgwko= +k8s.io/apiextensions-apiserver v0.26.2/go.mod h1:Y7UPgch8nph8mGCuVk0SK83LnS8Esf3n6fUBgew8SH8= +k8s.io/apimachinery v0.26.2 h1:da1u3D5wfR5u2RpLhE/ZtZS2P7QvDgLZTi9wrNZl/tQ= +k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= +k8s.io/client-go v0.26.2 h1:s1WkVujHX3kTp4Zn4yGNFK+dlDXy1bAAkIl+cFAiuYI= +k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU= +k8s.io/component-base v0.26.2 h1:IfWgCGUDzrD6wLLgXEstJKYZKAFS2kO+rBRi0p3LqcI= +k8s.io/component-base v0.26.2/go.mod h1:DxbuIe9M3IZPRxPIzhch2m1eT7uFrSBJUBuVCQEBivs= k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9 h1:iu3o/SxaHVI7tKPtkGzD3M9IzrE21j+CUKH98NQJ8Ms= k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= @@ -1043,18 +1044,18 @@ k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.90.0 h1:VkTxIV/FjRXn1fgNNcKGM8cfmL1Z33ZjXRTVxKCoF5M= -k8s.io/klog/v2 v2.90.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20230224204730-66828de6f33b h1:4dkmFEDQj0ZBLKCxJ0R+qzhvZmEvRdRaaZAE06tR/Lg= -k8s.io/kube-openapi v0.0.0-20230224204730-66828de6f33b/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY= +k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= +k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d h1:VcFq5n7wCJB2FQMCIHfC+f+jNcGgNMar1uKd6rVlifU= +k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY= k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk= k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/controller-runtime v0.14.4 h1:Kd/Qgx5pd2XUL08eOV2vwIq3L9GhIbJ5Nxengbd4/0M= -sigs.k8s.io/controller-runtime v0.14.4/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= +sigs.k8s.io/controller-runtime v0.14.5 h1:6xaWFqzT5KuAQ9ufgUaj1G/+C4Y1GRkhrxl+BJ9i+5s= +sigs.k8s.io/controller-runtime v0.14.5/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= sigs.k8s.io/controller-tools v0.11.3 h1:T1xzLkog9saiyQSLz1XOImu4OcbdXWytc5cmYsBeBiE= sigs.k8s.io/controller-tools v0.11.3/go.mod h1:qcfX7jfcfYD/b7lAhvqAyTbt/px4GpvN88WKLFFv7p8= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= From c5414567406279cfb06bda4e111a01c251861af5 Mon Sep 17 00:00:00 2001 From: Emin Alemdar <77338109+eminalemdar@users.noreply.github.com> Date: Mon, 6 Mar 2023 23:08:44 +0300 Subject: [PATCH 43/62] Added AWS Containers from the Couch Session (#2050) I've added my recent live session about ESO from the AWS Container from the Couch YouTube channel Signed-off-by: Emin Alemdar <77338109+eminalemdar@users.noreply.github.com> --- docs/eso-talks.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/eso-talks.md b/docs/eso-talks.md index 8ae483e9b27..1060e16900b 100644 --- a/docs/eso-talks.md +++ b/docs/eso-talks.md @@ -17,3 +17,7 @@ A list of talks given by people at conferences and events. Feel free to let us k ## Kubernetes Community Days UK - 2022 [![Kubernetes Community Days UK 2022](https://img.youtube.com/vi/TEV13ELPhI8/0.jpg)](https://www.youtube.com/watch?v=TEV13ELPhI8) + +## AWS Containers from the Couch + +[![AWS Containers from the Couch](https://img.youtube.com/vi/FityN80Cpto/0.jpg)](https://www.youtube.com/watch?v=FityN80Cpto) From 2a1b95cc6cf96cc5efef9198e3be9e225f70858b Mon Sep 17 00:00:00 2001 From: YurNaybor <55484313+YurNaybor@users.noreply.github.com> Date: Mon, 6 Mar 2023 21:58:37 +0100 Subject: [PATCH 44/62] Add values for extraContainers in deployment (#2073) Signed-off-by: Benjamin Voigt <55484313+YurNaybor@users.noreply.github.com> --- deploy/charts/external-secrets/README.md | 1 + deploy/charts/external-secrets/templates/deployment.yaml | 3 +++ deploy/charts/external-secrets/values.yaml | 3 +++ 3 files changed, 7 insertions(+) diff --git a/deploy/charts/external-secrets/README.md b/deploy/charts/external-secrets/README.md index c29f33250fe..00c316d268d 100644 --- a/deploy/charts/external-secrets/README.md +++ b/deploy/charts/external-secrets/README.md @@ -84,6 +84,7 @@ The command removes all the Kubernetes components associated with the chart and | deploymentAnnotations | object | `{}` | Annotations to add to Deployment | | dnsConfig | object | `{}` | Specifies `dnsOptions` to deployment | | extraArgs | object | `{}` | | +| extraContainers | list | `[]` | | | extraEnv | list | `[]` | | | extraVolumeMounts | list | `[]` | | | extraVolumes | list | `[]` | | diff --git a/deploy/charts/external-secrets/templates/deployment.yaml b/deploy/charts/external-secrets/templates/deployment.yaml index 6c7442de0fa..47c9610ef0b 100644 --- a/deploy/charts/external-secrets/templates/deployment.yaml +++ b/deploy/charts/external-secrets/templates/deployment.yaml @@ -95,6 +95,9 @@ spec: volumeMounts: {{- toYaml .Values.extraVolumeMounts | nindent 12 }} {{- end }} + {{- if .Values.extraContainers }} + {{ toYaml .Values.extraContainers | nindent 8}} + {{- end }} {{- if .Values.dnsConfig }} dnsConfig: {{- toYaml .Values.dnsConfig | nindent 8 }} diff --git a/deploy/charts/external-secrets/values.yaml b/deploy/charts/external-secrets/values.yaml index fe4a6d8fc28..b02a3ee8646 100644 --- a/deploy/charts/external-secrets/values.yaml +++ b/deploy/charts/external-secrets/values.yaml @@ -85,6 +85,9 @@ extraVolumes: [] ## -- Extra volumes to mount to the container. extraVolumeMounts: [] +## -- Extra containers to add to the pod. +extraContainers: [] + # -- Annotations to add to Deployment deploymentAnnotations: {} From aa335219356dc7529a31e145b4bc28764dd52e1a Mon Sep 17 00:00:00 2001 From: Alexandre Desjardins Date: Mon, 6 Mar 2023 17:00:45 -0500 Subject: [PATCH 45/62] feat(helm): add topologySpreadConstraints to helm chart (#2084) * feat(helm): add topologySpreadConstraints to helm chart Fixes #2083 Signed-off-by: jemag * fix(helm): generate helm doc properly for topologySpreadConstraints Signed-off-by: jemag --------- Signed-off-by: jemag --- deploy/charts/external-secrets/README.md | 1 + deploy/charts/external-secrets/templates/deployment.yaml | 4 ++++ deploy/charts/external-secrets/values.yaml | 2 ++ 3 files changed, 7 insertions(+) diff --git a/deploy/charts/external-secrets/README.md b/deploy/charts/external-secrets/README.md index 00c316d268d..d6d5ddd1cee 100644 --- a/deploy/charts/external-secrets/README.md +++ b/deploy/charts/external-secrets/README.md @@ -129,6 +129,7 @@ The command removes all the Kubernetes components associated with the chart and | serviceMonitor.relabelings | list | `[]` | Relabel configs to apply to samples before ingestion. [Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config) | | serviceMonitor.scrapeTimeout | string | `"25s"` | Timeout if metrics can't be retrieved in given time interval | | tolerations | list | `[]` | | +| topologySpreadConstraints | list | `[]` | | | webhook.affinity | object | `{}` | | | webhook.certCheckInterval | string | `"5m"` | Specifices the time to check if the cert is valid | | webhook.certDir | string | `"/tmp/certs"` | | diff --git a/deploy/charts/external-secrets/templates/deployment.yaml b/deploy/charts/external-secrets/templates/deployment.yaml index 47c9610ef0b..4760683dcf8 100644 --- a/deploy/charts/external-secrets/templates/deployment.yaml +++ b/deploy/charts/external-secrets/templates/deployment.yaml @@ -118,6 +118,10 @@ spec: tolerations: {{- toYaml . | nindent 8 }} {{- end }} + {{- with .Values.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} {{- if .Values.priorityClassName }} priorityClassName: {{ .Values.priorityClassName }} {{- end }} diff --git a/deploy/charts/external-secrets/values.yaml b/deploy/charts/external-secrets/values.yaml index b02a3ee8646..7288e302a91 100644 --- a/deploy/charts/external-secrets/values.yaml +++ b/deploy/charts/external-secrets/values.yaml @@ -168,6 +168,8 @@ nodeSelector: {} tolerations: [] +topologySpreadConstraints: [] + affinity: {} # -- Pod priority class name. From 7e5fbb124b4cb24db7b7765bc061b7b1ff2abfda Mon Sep 17 00:00:00 2001 From: renanaAkeyless Date: Tue, 7 Mar 2023 14:11:02 +0200 Subject: [PATCH 46/62] :sparkles: Add CABundle/CAProvider to Akeyless provider (#2092) * support adding CA Cert in Akeyless provider Signed-off-by: Docs * update akeyless-go to v3 Signed-off-by: Docs * update description Signed-off-by: Docs * update description Signed-off-by: Docs * update description Signed-off-by: Docs * update description Signed-off-by: Docs * fix comments Signed-off-by: Docs --------- Signed-off-by: Docs --- .../v1alpha1/secretstore_akeyless_types.go | 10 + .../v1alpha1/zz_generated.deepcopy.go | 10 + .../v1beta1/secretstore_akeyless_types.go | 10 + .../v1beta1/zz_generated.deepcopy.go | 10 + ...ternal-secrets.io_clustersecretstores.yaml | 67 ++++++ .../external-secrets.io_secretstores.yaml | 67 ++++++ deploy/crds/bundle.yaml | 104 +++++++++ docs/api/spec.md | 29 +++ docs/introduction/stability-support.md | 4 +- docs/provider/akeyless.md | 79 +++++-- .../akeyless-external-secret-json.yaml | 2 +- docs/snippets/full-cluster-secret-store.yaml | 2 +- e2e/go.mod | 2 +- e2e/go.sum | 4 +- .../provider/cases/akeyless/provider.go | 2 +- go.mod | 2 +- go.sum | 4 +- pkg/provider/akeyless/akeyless.go | 216 +++++++++++++++++- pkg/provider/akeyless/akeyless_api.go | 126 ++++++---- pkg/provider/akeyless/fake/fake.go | 6 +- pkg/provider/akeyless/utils.go | 10 + 21 files changed, 677 insertions(+), 89 deletions(-) diff --git a/apis/externalsecrets/v1alpha1/secretstore_akeyless_types.go b/apis/externalsecrets/v1alpha1/secretstore_akeyless_types.go index dde978cc007..2e1bbf733d5 100644 --- a/apis/externalsecrets/v1alpha1/secretstore_akeyless_types.go +++ b/apis/externalsecrets/v1alpha1/secretstore_akeyless_types.go @@ -26,6 +26,16 @@ type AkeylessProvider struct { // Auth configures how the operator authenticates with Akeyless. Auth *AkeylessAuth `json:"authSecretRef"` + + // PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used + // if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates + // are used to validate the TLS connection. + // +optional + CABundle []byte `json:"caBundle,omitempty"` + + // The provider for the CA bundle to use to validate Akeyless Gateway certificate. + // +optional + CAProvider *CAProvider `json:"caProvider,omitempty"` } type AkeylessAuth struct { diff --git a/apis/externalsecrets/v1alpha1/zz_generated.deepcopy.go b/apis/externalsecrets/v1alpha1/zz_generated.deepcopy.go index 9af10424500..5e9e1bc9b20 100644 --- a/apis/externalsecrets/v1alpha1/zz_generated.deepcopy.go +++ b/apis/externalsecrets/v1alpha1/zz_generated.deepcopy.go @@ -180,6 +180,16 @@ func (in *AkeylessProvider) DeepCopyInto(out *AkeylessProvider) { *out = new(AkeylessAuth) (*in).DeepCopyInto(*out) } + if in.CABundle != nil { + in, out := &in.CABundle, &out.CABundle + *out = make([]byte, len(*in)) + copy(*out, *in) + } + if in.CAProvider != nil { + in, out := &in.CAProvider, &out.CAProvider + *out = new(CAProvider) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AkeylessProvider. diff --git a/apis/externalsecrets/v1beta1/secretstore_akeyless_types.go b/apis/externalsecrets/v1beta1/secretstore_akeyless_types.go index 0e37236490a..58982e26b19 100644 --- a/apis/externalsecrets/v1beta1/secretstore_akeyless_types.go +++ b/apis/externalsecrets/v1beta1/secretstore_akeyless_types.go @@ -26,6 +26,16 @@ type AkeylessProvider struct { // Auth configures how the operator authenticates with Akeyless. Auth *AkeylessAuth `json:"authSecretRef"` + + // PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used + // if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates + // are used to validate the TLS connection. + // +optional + CABundle []byte `json:"caBundle,omitempty"` + + // The provider for the CA bundle to use to validate Akeyless Gateway certificate. + // +optional + CAProvider *CAProvider `json:"caProvider,omitempty"` } type AkeylessAuth struct { diff --git a/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go b/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go index bd18e46f7da..101493141a6 100644 --- a/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go +++ b/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go @@ -190,6 +190,16 @@ func (in *AkeylessProvider) DeepCopyInto(out *AkeylessProvider) { *out = new(AkeylessAuth) (*in).DeepCopyInto(*out) } + if in.CABundle != nil { + in, out := &in.CABundle, &out.CABundle + *out = make([]byte, len(*in)) + copy(*out, *in) + } + if in.CAProvider != nil { + in, out := &in.CAProvider, &out.CAProvider + *out = new(CAProvider) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AkeylessProvider. diff --git a/config/crds/bases/external-secrets.io_clustersecretstores.yaml b/config/crds/bases/external-secrets.io_clustersecretstores.yaml index 15b95136005..6c1c7870a9a 100644 --- a/config/crds/bases/external-secrets.io_clustersecretstores.yaml +++ b/config/crds/bases/external-secrets.io_clustersecretstores.yaml @@ -210,6 +210,39 @@ spec: type: object type: object type: object + caBundle: + description: PEM/base64 encoded CA bundle used to validate + Akeyless Gateway certificate. Only used if the AkeylessGWApiURL + URL is using HTTPS protocol. If not set the system root + certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate + Akeyless Gateway certificate. + properties: + key: + description: The key the value inside of the provider + type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider + type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", + or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object required: - akeylessGWApiURL - authSecretRef @@ -1762,6 +1795,40 @@ spec: type: object type: object type: object + caBundle: + description: PEM/base64 encoded CA bundle used to validate + Akeyless Gateway certificate. Only used if the AkeylessGWApiURL + URL is using HTTPS protocol. If not set the system root + certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate + Akeyless Gateway certificate. + properties: + key: + description: The key where the CA certificate can be found + in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider + type. + type: string + namespace: + description: The namespace the Provider type is in. Can + only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", + or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object required: - akeylessGWApiURL - authSecretRef diff --git a/config/crds/bases/external-secrets.io_secretstores.yaml b/config/crds/bases/external-secrets.io_secretstores.yaml index 54ba2bf5492..c6a6d6c4059 100644 --- a/config/crds/bases/external-secrets.io_secretstores.yaml +++ b/config/crds/bases/external-secrets.io_secretstores.yaml @@ -210,6 +210,39 @@ spec: type: object type: object type: object + caBundle: + description: PEM/base64 encoded CA bundle used to validate + Akeyless Gateway certificate. Only used if the AkeylessGWApiURL + URL is using HTTPS protocol. If not set the system root + certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate + Akeyless Gateway certificate. + properties: + key: + description: The key the value inside of the provider + type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider + type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", + or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object required: - akeylessGWApiURL - authSecretRef @@ -1762,6 +1795,40 @@ spec: type: object type: object type: object + caBundle: + description: PEM/base64 encoded CA bundle used to validate + Akeyless Gateway certificate. Only used if the AkeylessGWApiURL + URL is using HTTPS protocol. If not set the system root + certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate + Akeyless Gateway certificate. + properties: + key: + description: The key where the CA certificate can be found + in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider + type. + type: string + namespace: + description: The namespace the Provider type is in. Can + only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", + or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object required: - akeylessGWApiURL - authSecretRef diff --git a/deploy/crds/bundle.yaml b/deploy/crds/bundle.yaml index c5575334855..bae0a285034 100644 --- a/deploy/crds/bundle.yaml +++ b/deploy/crds/bundle.yaml @@ -600,6 +600,32 @@ spec: type: object type: object type: object + caBundle: + description: PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object required: - akeylessGWApiURL - authSecretRef @@ -1723,6 +1749,32 @@ spec: type: object type: object type: object + caBundle: + description: PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. + properties: + key: + description: The key where the CA certificate can be found in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. Can only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object required: - akeylessGWApiURL - authSecretRef @@ -3915,6 +3967,32 @@ spec: type: object type: object type: object + caBundle: + description: PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object required: - akeylessGWApiURL - authSecretRef @@ -5038,6 +5116,32 @@ spec: type: object type: object type: object + caBundle: + description: PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. + properties: + key: + description: The key where the CA certificate can be found in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. Can only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object required: - akeylessGWApiURL - authSecretRef diff --git a/docs/api/spec.md b/docs/api/spec.md index 61e53fccdf9..203166c2f4e 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -479,6 +479,34 @@ AkeylessAuth

Auth configures how the operator authenticates with Akeyless.

+ + +caBundle
+ +[]byte + + + +(Optional) +

PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used +if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates +are used to validate the TLS connection.

+ + + + +caProvider
+ + +CAProvider + + + + +(Optional) +

The provider for the CA bundle to use to validate Akeyless Gateway certificate.

+ +

AlibabaAuth @@ -836,6 +864,7 @@ string

(Appears on: +AkeylessProvider, KubernetesServer, VaultProvider)

diff --git a/docs/introduction/stability-support.md b/docs/introduction/stability-support.md index 8d491fd788f..0706ddf44f4 100644 --- a/docs/introduction/stability-support.md +++ b/docs/introduction/stability-support.md @@ -45,7 +45,7 @@ The following table describes the stability level of each provider and who's res The following table show the support for features across different providers. | Provider | find by name | find by tags | metadataPolicy Fetch | referent authentication | store validation | push secret | DeletionPolicy Merge/Delete | -|---------------------------|:------------:|:------------:| :------------------: | :---------------------: | :--------------: | :---------: | :-------------------------: +|---------------------------|:------------:|:------------:| :------------------: | :---------------------: | :--------------: | :---------: | :-------------------------: | AWS Secrets Manager | x | x | | x | x | x | x | | AWS Parameter Store | x | x | | x | x | x | x | | Hashicorp Vault | x | x | | x | x | x | x | @@ -57,7 +57,7 @@ The following table show the support for features across different providers. | Gitlab Variables | x | x | | | x | | | | Alibaba Cloud KMS | | | | | x | | | | Oracle Vault | | | | | x | | | -| Akeyless | | | | | x | | | +| Akeyless | x | x | | | x | | | | 1Password | x | | | | x | | | | Generic Webhook | | | | | | | x | | senhasegura DSM | | | | | x | | | diff --git a/docs/provider/akeyless.md b/docs/provider/akeyless.md index 2f4324ebe33..2dfe9ef3de3 100644 --- a/docs/provider/akeyless.md +++ b/docs/provider/akeyless.md @@ -1,24 +1,46 @@ -## Akeyless Vault +## Akeyless Secrets Management Platform -External Secrets Operator integrates with the [Akeyless API](https://docs.akeyless.io/reference#v2). +External Secrets Operator integrates with the [Akeyless Secrets Management Platform](https://www.akeyless.io/). +### Create Secret Store: +SecretStore resource specifies how to access Akeyless. This resource is namespaced. -### Authentication +**NOTE:** Make sure the Akeyless provider is listed in the Kind=SecretStore. +If you use a customer fragment, define the value of akeylessGWApiURL as the URL of your Akeyless Gateway in the following format: https://your.akeyless.gw:8080/v2. -To operate the API first define an access-id, access-type and access-Type-param. +Akeyelss provide several Authentication Methods: + +### Authentication with Kubernetes: + +Options for obtaining Kubernetes credentials include: + +1. Using a service account jwt referenced in serviceAccountRef +2. Using the jwt from a Kind=Secret referenced by the secretRef +3. Using transient credentials from the mounted service account token within the external-secrets operator + +#### Create the Akeyless Secret Store Provider with Kubernetes Auth-Method +```yaml +{% include 'akeyless-secret-store-k8s-auth.yaml' %} +``` +**NOTE:** In case of a `ClusterSecretStore`, Be sure to provide `namespace` for `serviceAccountRef` and `secretRef` according to the namespaces where the secrets reside. + + +### Authentication With Cloud-Identity or Api-Access-Key + +Akeyless providers require an access-id, access-type and access-Type-param +To set your SecretStore with an authentication method from Akeyless. The supported auth-methods and their parameters are: | accessType | accessTypeParam | | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `api_key` | The access key. | -| `k8s` | The k8s configuration name | | `aws_iam` | - | | `gcp` | The gcp audience | | `azure_ad` | azure object id (optional) | - +| `api_key` | The access key. | +| `k8s` | The k8s configuration name | For more information see [Akeyless Authentication Methods](https://docs.akeyless.io/docs/access-and-authentication-methods) -### Creating an Akeyless Ccredentials Secret +#### Creating an Akeyless Credentials Secret Create a secret containing your credentials using the following example as a guide: @@ -30,31 +52,38 @@ metadata: type: Opaque stringData: accessId: "p-XXXX" - accessType: # k8s/aws_iam/gcp/azure_ad/api_key - accessTypeParam: # can be one of the following: k8s-conf-name/gcp-audience/azure-obj-id/access-key + accessType: # gcp/azure_ad/api_key/k8s/aws_iam + accessTypeParam: # optional: can be one of the following: gcp-audience/azure-obj-id/access-key/k8s-conf-name ``` -### Update Secret Store -Be sure the `akeyless` provider is listed in the `Kind=SecretStore` and the `akeylessGWApiURL` is set (def: "https://api.akeless.io"). +#### Create the Akeyless Secret Store Provider with the Credentials Secret ```yaml {% include 'akeyless-secret-store.yaml' %} ``` **NOTE:** In case of a `ClusterSecretStore`, be sure to provide `namespace` for `accessID`, `accessType` and `accessTypeParam` according to the namespaces where the secrets reside. -### Authentication with Kubernetes - -Options for obtaining Kubernetes credentials include: - -1. Using a service account jwt referenced in serviceAccountRef -2. Using the jwt from a Kind=Secret referenced by the secretRef -3. Using transient credentials from the mounted service account token within the external-secrets operator - +#### Create the Akeyless Secret Store With CAs for TLS handshake ```yaml -{% include 'akeyless-secret-store-k8s-auth.yaml' %} +.... +spec: + provider: + akeyless: + akeylessGWApiURL: "https://your.akeyless.gw:8080/v2" + + # Optional caBundle - PEM/base64 encoded CA certificate + caBundle: "" + # Optional caProvider: + # Instead of caBundle you can also specify a caProvider + # this will retrieve the cert from a Secret or ConfigMap + caProvider: + type: "Secret/ConfigMap" # Can be Secret or ConfigMap + name: "" + key: "" + # namespace is mandatory for ClusterSecretStore and not relevant for SecretStore + namespace: "my-cert-secret-namespace" + .... ``` -**NOTE:** In case of a `ClusterSecretStore`, Be sure to provide `namespace` for `serviceAccountRef` and `secretRef` according to the namespaces where the secrets reside. - ### Creating an external secret @@ -76,9 +105,9 @@ DataFrom can be used to get a secret as a JSON string and attempt to parse it. ### Getting the Kubernetes Secret The operator will fetch the secret and inject it as a `Kind=Secret`. ``` -kubectl get secret akeyless-secret-to-create -o jsonpath='{.data.secretKey}' | base64 -d +kubectl get secret database-credentials -o jsonpath='{.data.db-password}' | base64 -d ``` ``` -kubectl get secret akeyless-secret-to-create-json -o jsonpath='{.data}' +kubectl get secret database-credentials-json -o jsonpath='{.data}' ``` diff --git a/docs/snippets/akeyless-external-secret-json.yaml b/docs/snippets/akeyless-external-secret-json.yaml index 5b9824dc879..765ddc5c94c 100644 --- a/docs/snippets/akeyless-external-secret-json.yaml +++ b/docs/snippets/akeyless-external-secret-json.yaml @@ -10,7 +10,7 @@ spec: name: akeyless-secret-store # Must match SecretStore on the cluster target: - name: database-credentials # Name for the secret to be created on the cluster + name: database-credentials-json # Name for the secret to be created on the cluster creationPolicy: Owner # for json formatted secrets: each key in the json will be used as the secret key in the SECRET k8s target object diff --git a/docs/snippets/full-cluster-secret-store.yaml b/docs/snippets/full-cluster-secret-store.yaml index 9f8499b3ce5..6a837caf9d0 100644 --- a/docs/snippets/full-cluster-secret-store.yaml +++ b/docs/snippets/full-cluster-secret-store.yaml @@ -53,7 +53,7 @@ spec: caProvider: # Can be Secret or ConfigMap type: "Secret" - # This is mandatory for ClusterSecretStore and not relevant for SecretStore + # namespace is mandatory for ClusterSecretStore and not relevant for SecretStore namespace: "my-cert-secret-namespace" name: "my-cert-secret" key: "cert-key" diff --git a/e2e/go.mod b/e2e/go.mod index a0b9969b6a1..c2cf641b3b2 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -42,7 +42,7 @@ require ( github.com/Azure/azure-sdk-for-go v68.0.0+incompatible github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 - github.com/akeylesslabs/akeyless-go/v2 v2.20.3 + github.com/akeylesslabs/akeyless-go/v3 v3.2.6 github.com/aliyun/alibaba-cloud-sdk-go v1.62.217 github.com/argoproj/argo-cd/v2 v2.4.8 github.com/aws/aws-sdk-go v1.44.214 diff --git a/e2e/go.sum b/e2e/go.sum index 937331d9e32..81fa3497fe1 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -115,8 +115,8 @@ github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 h1:vTckjyBhHOBiOWSC/oaEU2Oo4OH5eAlQiwKu2RMxsFg= github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4/go.mod h1:As/RomC2w/fa3y+yHRlVHPmkbP+zrKBFRow41y5dk+E= -github.com/akeylesslabs/akeyless-go/v2 v2.20.3 h1:NIRMynmpQbfgQyRLf5DMQC8p5iLgaUu1MXBB4ijLCxM= -github.com/akeylesslabs/akeyless-go/v2 v2.20.3/go.mod h1:uOdXD49NCCe4rexeSc2aBU5Qv4KZgJE6YlbtYalvb+I= +github.com/akeylesslabs/akeyless-go/v3 v3.2.6 h1:7Z5m/oANHvRWKKWhOuTNX26OalNX20qSqxR7qVyOcLU= +github.com/akeylesslabs/akeyless-go/v3 v3.2.6/go.mod h1:XtPdOYw+rrG9bxyBzuQ5zAGCUTd364R2grs7GsZ5nos= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= diff --git a/e2e/suites/provider/cases/akeyless/provider.go b/e2e/suites/provider/cases/akeyless/provider.go index a5f3992abb4..c1bdb5c3f09 100644 --- a/e2e/suites/provider/cases/akeyless/provider.go +++ b/e2e/suites/provider/cases/akeyless/provider.go @@ -26,7 +26,7 @@ import ( aws_cloud_id "github.com/akeylesslabs/akeyless-go-cloud-id/cloudprovider/aws" azure_cloud_id "github.com/akeylesslabs/akeyless-go-cloud-id/cloudprovider/azure" gcp_cloud_id "github.com/akeylesslabs/akeyless-go-cloud-id/cloudprovider/gcp" - "github.com/akeylesslabs/akeyless-go/v2" + "github.com/akeylesslabs/akeyless-go/v3" //nolint . "github.com/onsi/ginkgo/v2" diff --git a/go.mod b/go.mod index efff732a7fc..27071ebd7a3 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,6 @@ require ( github.com/PaesslerAG/jsonpath v0.1.1 github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 - github.com/akeylesslabs/akeyless-go/v2 v2.20.3 github.com/aliyun/alibaba-cloud-sdk-go v1.62.217 github.com/aws/aws-sdk-go v1.44.214 github.com/go-logr/logr v1.2.3 @@ -65,6 +64,7 @@ require github.com/1Password/connect-sdk-go v1.5.0 require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 + github.com/akeylesslabs/akeyless-go/v3 v3.2.6 github.com/hashicorp/golang-lru v0.5.4 github.com/keeper-security/secrets-manager-go/core v1.5.0 github.com/maxbrunsfeld/counterfeiter/v6 v6.6.1 diff --git a/go.sum b/go.sum index d9d0f491f3e..ccb752bbd10 100644 --- a/go.sum +++ b/go.sum @@ -110,8 +110,8 @@ github.com/ahmetb/gen-crd-api-reference-docs v0.3.0/go.mod h1:TdjdkYhlOifCQWPs1U github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 h1:vTckjyBhHOBiOWSC/oaEU2Oo4OH5eAlQiwKu2RMxsFg= github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4/go.mod h1:As/RomC2w/fa3y+yHRlVHPmkbP+zrKBFRow41y5dk+E= -github.com/akeylesslabs/akeyless-go/v2 v2.20.3 h1:NIRMynmpQbfgQyRLf5DMQC8p5iLgaUu1MXBB4ijLCxM= -github.com/akeylesslabs/akeyless-go/v2 v2.20.3/go.mod h1:uOdXD49NCCe4rexeSc2aBU5Qv4KZgJE6YlbtYalvb+I= +github.com/akeylesslabs/akeyless-go/v3 v3.2.6 h1:7Z5m/oANHvRWKKWhOuTNX26OalNX20qSqxR7qVyOcLU= +github.com/akeylesslabs/akeyless-go/v3 v3.2.6/go.mod h1:XtPdOYw+rrG9bxyBzuQ5zAGCUTd364R2grs7GsZ5nos= github.com/aliyun/alibaba-cloud-sdk-go v1.62.217 h1:YZPv3FMTEP9s5u547eY3E+7s8FothzjWvITtqwhljSE= github.com/aliyun/alibaba-cloud-sdk-go v1.62.217/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= diff --git a/pkg/provider/akeyless/akeyless.go b/pkg/provider/akeyless/akeyless.go index bd518716629..8ec1567aea6 100644 --- a/pkg/provider/akeyless/akeyless.go +++ b/pkg/provider/akeyless/akeyless.go @@ -16,19 +16,27 @@ package akeyless import ( "context" + "crypto/tls" + "crypto/x509" "encoding/json" + "errors" "fmt" + "net/http" "net/url" "strconv" + "strings" "time" - "github.com/akeylesslabs/akeyless-go/v2" + "github.com/akeylesslabs/akeyless-go/v3" + corev1 "k8s.io/api/core/v1" "k8s.io/client-go/kubernetes" typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config" esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" + esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" + "github.com/external-secrets/external-secrets/pkg/find" "github.com/external-secrets/external-secrets/pkg/utils" ) @@ -47,6 +55,7 @@ type Provider struct{} type akeylessBase struct { kube client.Client store esv1beta1.GenericStore + storeKind string corev1 typedcorev1.CoreV1Interface namespace string @@ -60,8 +69,9 @@ type Akeyless struct { } type akeylessVaultInterface interface { - GetSecretByType(secretName, token string, version int32) (string, error) + GetSecretByType(ctx context.Context, secretName, token string, version int32) (string, error) TokenFromSecretRef(ctx context.Context) (string, error) + ListSecrets(ctx context.Context, path, tag, token string) ([]string, error) } func init() { @@ -166,6 +176,7 @@ func newClient(_ context.Context, store esv1beta1.GenericStore, kube client.Clie store: store, namespace: namespace, corev1: corev1, + storeKind: store.GetObjectKind().GroupVersionKind().Kind, } spec, err := GetAKeylessProvider(store) @@ -181,7 +192,13 @@ func newClient(_ context.Context, store esv1beta1.GenericStore, kube client.Clie return nil, fmt.Errorf("missing Auth in store config") } + client, err := akl.getAkeylessHTTPClient(spec) + if err != nil { + return nil, err + } + RestAPIClient := akeyless.NewAPIClient(&akeyless.Configuration{ + HTTPClient: client, Servers: []akeyless.ServerConfiguration{ { URL: akeylessGwAPIURL, @@ -235,17 +252,98 @@ func (a *Akeyless) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDa version = int32(i) } } - value, err := a.Client.GetSecretByType(ref.Key, token, version) + value, err := a.Client.GetSecretByType(ctx, ref.Key, token, version) if err != nil { return nil, err } return []byte(value), nil } -// Empty GetAllSecrets. +// Implements store.Client.GetAllSecrets Interface. +// Retrieves a all secrets with defined in ref.Name or tags. func (a *Akeyless) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) { - // TO be implemented - return nil, fmt.Errorf("GetAllSecrets not implemented") + if utils.IsNil(a.Client) { + return nil, fmt.Errorf(errUninitalizedAkeylessProvider) + } + + searchPath := "" + if ref.Path != nil { + searchPath = *ref.Path + if !strings.HasPrefix(searchPath, "/") { + searchPath = "/" + searchPath + } + if !strings.HasSuffix(searchPath, "/") { + searchPath += "/" + } + } + token, err := a.Client.TokenFromSecretRef(ctx) + if err != nil { + return nil, err + } + + if ref.Name != nil { + potentialSecrets, err := a.Client.ListSecrets(ctx, searchPath, "", token) + if err != nil { + return nil, err + } + if len(potentialSecrets) == 0 { + return nil, nil + } + return a.findSecretsFromName(ctx, potentialSecrets, *ref.Name, token) + } + if len(ref.Tags) > 0 { + var potentialSecretsName []string + for _, v := range ref.Tags { + potentialSecrets, err := a.Client.ListSecrets(ctx, searchPath, v, token) + if err != nil { + return nil, err + } + if len(potentialSecrets) > 0 { + potentialSecretsName = append(potentialSecretsName, potentialSecrets...) + } + } + if len(potentialSecretsName) == 0 { + return nil, nil + } + return a.getSecrets(ctx, potentialSecretsName, token) + } + + return nil, errors.New("unexpected find operator") +} + +func (a *Akeyless) getSecrets(ctx context.Context, candidates []string, token string) (map[string][]byte, error) { + secrets := make(map[string][]byte) + for _, name := range candidates { + secretValue, err := a.Client.GetSecretByType(ctx, name, token, 0) + if err != nil { + return nil, err + } + if secretValue != "" { + secrets[name] = []byte(secretValue) + } + } + return secrets, nil +} + +func (a *Akeyless) findSecretsFromName(ctx context.Context, candidates []string, ref esv1beta1.FindName, token string) (map[string][]byte, error) { + secrets := make(map[string][]byte) + matcher, err := find.New(ref) + if err != nil { + return nil, err + } + for _, name := range candidates { + ok := matcher.MatchName(name) + if ok { + secretValue, err := a.Client.GetSecretByType(ctx, name, token, 0) + if err != nil { + return nil, err + } + if secretValue != "" { + secrets[name] = []byte(secretValue) + } + } + } + return secrets, nil } // Implements store.Client.GetSecretMap Interface. @@ -273,3 +371,109 @@ func (a *Akeyless) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecre } return secretData, nil } + +func (a *akeylessBase) getAkeylessHTTPClient(provider *esv1beta1.AkeylessProvider) (*http.Client, error) { + client := &http.Client{Timeout: 30 * time.Second} + if len(provider.CABundle) == 0 && provider.CAProvider == nil { + return client, nil + } + caCertPool, err := a.getCACertPool(provider) + if err != nil { + return nil, err + } + + tlsConf := &tls.Config{ + RootCAs: caCertPool, + MinVersion: tls.VersionTLS12, + } + client.Transport = &http.Transport{TLSClientConfig: tlsConf} + return client, nil +} + +func (a *akeylessBase) getCACertPool(provider *esv1beta1.AkeylessProvider) (*x509.CertPool, error) { + caCertPool := x509.NewCertPool() + if len(provider.CABundle) > 0 { + pem, err := base64decode(provider.CABundle) + if err != nil { + pem = provider.CABundle + } + ok := caCertPool.AppendCertsFromPEM(pem) + if !ok { + return nil, fmt.Errorf("failed to append cabundle") + } + } + + if provider.CAProvider != nil && a.storeKind == esv1beta1.ClusterSecretStoreKind && provider.CAProvider.Namespace == nil { + return nil, fmt.Errorf("missing namespace on CAProvider secret") + } + + if provider.CAProvider != nil { + var cert []byte + var err error + + switch provider.CAProvider.Type { + case esv1beta1.CAProviderTypeSecret: + cert, err = a.getCertFromSecret(provider) + case esv1beta1.CAProviderTypeConfigMap: + cert, err = a.getCertFromConfigMap(provider) + default: + err = fmt.Errorf("unknown caprovider type: %s", provider.CAProvider.Type) + } + + if err != nil { + return nil, err + } + pem, err := base64decode(cert) + if err != nil { + pem = cert + } + ok := caCertPool.AppendCertsFromPEM(pem) + if !ok { + return nil, fmt.Errorf("failed to append cabundle") + } + } + return caCertPool, nil +} + +func (a *akeylessBase) getCertFromSecret(provider *esv1beta1.AkeylessProvider) ([]byte, error) { + secretRef := esmeta.SecretKeySelector{ + Name: provider.CAProvider.Name, + Key: provider.CAProvider.Key, + } + + if provider.CAProvider.Namespace != nil { + secretRef.Namespace = provider.CAProvider.Namespace + } + + ctx := context.Background() + res, err := a.secretKeyRef(ctx, &secretRef) + if err != nil { + return nil, err + } + + return []byte(res), nil +} + +func (a *akeylessBase) getCertFromConfigMap(provider *esv1beta1.AkeylessProvider) ([]byte, error) { + objKey := client.ObjectKey{ + Name: provider.CAProvider.Name, + } + + if provider.CAProvider.Namespace != nil { + objKey.Namespace = *provider.CAProvider.Namespace + } + + configMapRef := &corev1.ConfigMap{} + ctx := context.Background() + err := a.kube.Get(ctx, objKey, configMapRef) + if err != nil { + return nil, fmt.Errorf("failed to get caprovider secret %s: %w", objKey.Name, err) + } + + val, ok := configMapRef.Data[provider.CAProvider.Key] + if !ok { + return nil, fmt.Errorf("failed to get caprovider configmap %s -> %s", objKey.Name, provider.CAProvider.Key) + } + + return []byte(val), nil +} diff --git a/pkg/provider/akeyless/akeyless_api.go b/pkg/provider/akeyless/akeyless_api.go index f2bec119081..ec0627d7897 100644 --- a/pkg/provider/akeyless/akeyless_api.go +++ b/pkg/provider/akeyless/akeyless_api.go @@ -27,7 +27,7 @@ import ( aws_cloud_id "github.com/akeylesslabs/akeyless-go-cloud-id/cloudprovider/aws" azure_cloud_id "github.com/akeylesslabs/akeyless-go-cloud-id/cloudprovider/azure" gcp_cloud_id "github.com/akeylesslabs/akeyless-go-cloud-id/cloudprovider/gcp" - "github.com/akeylesslabs/akeyless-go/v2" + "github.com/akeylesslabs/akeyless-go/v3" authenticationv1 "k8s.io/api/authentication/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -79,8 +79,8 @@ func (a *akeylessBase) GetToken(accessID, accType, accTypeParam string, k8sAuth return token, nil } -func (a *akeylessBase) GetSecretByType(secretName, token string, version int32) (string, error) { - item, err := a.DescribeItem(secretName, token) +func (a *akeylessBase) GetSecretByType(ctx context.Context, secretName, token string, version int32) (string, error) { + item, err := a.DescribeItem(ctx, secretName, token) if err != nil { return "", err } @@ -88,19 +88,17 @@ func (a *akeylessBase) GetSecretByType(secretName, token string, version int32) switch secretType { case "STATIC_SECRET": - return a.GetStaticSecret(secretName, token, version) + return a.GetStaticSecret(ctx, secretName, token, version) case "DYNAMIC_SECRET": - return a.GetDynamicSecrets(secretName, token) + return a.GetDynamicSecrets(ctx, secretName, token) case "ROTATED_SECRET": - return a.GetRotatedSecrets(secretName, token, version) + return a.GetRotatedSecrets(ctx, secretName, token, version) default: return "", fmt.Errorf("invalid item type: %v", secretType) } } -func (a *akeylessBase) DescribeItem(itemName, token string) (*akeyless.Item, error) { - ctx := context.Background() - +func (a *akeylessBase) DescribeItem(ctx context.Context, itemName, token string) (*akeyless.Item, error) { body := akeyless.DescribeItem{ Name: itemName, } @@ -116,14 +114,12 @@ func (a *akeylessBase) DescribeItem(itemName, token string) (*akeyless.Item, err } return nil, fmt.Errorf("can't describe item: %w", err) } - res.Body.Close() + defer res.Body.Close() return &gsvOut, nil } -func (a *akeylessBase) GetRotatedSecrets(secretName, token string, version int32) (string, error) { - ctx := context.Background() - +func (a *akeylessBase) GetRotatedSecrets(ctx context.Context, secretName, token string, version int32) (string, error) { body := akeyless.GetRotatedSecretValue{ Names: secretName, Version: &version, @@ -141,7 +137,7 @@ func (a *akeylessBase) GetRotatedSecrets(secretName, token string, version int32 } return "", fmt.Errorf("can't get rotated secret value: %w", err) } - res.Body.Close() + defer res.Body.Close() valI, ok := gsvOut["value"] if ok { @@ -172,9 +168,7 @@ func (a *akeylessBase) GetRotatedSecrets(secretName, token string, version int32 return string(out), nil } -func (a *akeylessBase) GetDynamicSecrets(secretName, token string) (string, error) { - ctx := context.Background() - +func (a *akeylessBase) GetDynamicSecrets(ctx context.Context, secretName, token string) (string, error) { body := akeyless.GetDynamicSecretValue{ Name: secretName, } @@ -191,7 +185,7 @@ func (a *akeylessBase) GetDynamicSecrets(secretName, token string) (string, erro } return "", fmt.Errorf("can't get dynamic secret value: %w", err) } - res.Body.Close() + defer res.Body.Close() out, err := json.Marshal(gsvOut) if err != nil { @@ -201,9 +195,7 @@ func (a *akeylessBase) GetDynamicSecrets(secretName, token string) (string, erro return string(out), nil } -func (a *akeylessBase) GetStaticSecret(secretName, token string, version int32) (string, error) { - ctx := context.Background() - +func (a *akeylessBase) GetStaticSecret(ctx context.Context, secretName, token string, version int32) (string, error) { gsvBody := akeyless.GetSecretValue{ Names: []string{secretName}, Version: &version, @@ -222,7 +214,7 @@ func (a *akeylessBase) GetStaticSecret(secretName, token string, version int32) } return "", fmt.Errorf("can't get secret value: %w", err) } - res.Body.Close() + defer res.Body.Close() val, ok := gsvOut[secretName] if !ok { return "", fmt.Errorf("can't get secret: %v", secretName) @@ -248,30 +240,72 @@ func (a *akeylessBase) getCloudID(provider, accTypeParam string) (string, error) return cloudID, err } -func (a *akeylessBase) getK8SServiceAccountJWT(ctx context.Context, kubernetesAuth *esv1beta1.AkeylessKubernetesAuth) (string, error) { - if kubernetesAuth != nil && kubernetesAuth.ServiceAccountRef != nil { - // Kubernetes =v1.24: fetch token via TokenRequest API - jwt, err = a.getJWTfromServiceAccountToken(ctx, *kubernetesAuth.ServiceAccountRef, nil, 600) - if err != nil { - return "", err +func (a *akeylessBase) ListSecrets(ctx context.Context, path, tag, token string) ([]string, error) { + secretTypes := &[]string{"static-secret", "dynamic-secret", "rotated-secret"} + MinimalView := true + if tag != "" { + MinimalView = false + } + gsvBody := akeyless.ListItems{ + Filter: &path, + Type: secretTypes, + MinimalView: &MinimalView, + Tag: &tag, + } + + if strings.HasPrefix(token, "u-") { + gsvBody.UidToken = &token + } else { + gsvBody.Token = &token + } + + lipOut, res, err := a.RestAPI.ListItems(ctx).Body(gsvBody).Execute() + if err != nil { + if errors.As(err, &apiErr) { + return nil, fmt.Errorf("can't get secrets list: %v", string(apiErr.Body())) } - return jwt, nil - } else if kubernetesAuth != nil && kubernetesAuth.SecretRef != nil { - tokenRef := kubernetesAuth.SecretRef - if tokenRef.Key == "" { - tokenRef = kubernetesAuth.SecretRef.DeepCopy() - tokenRef.Key = "token" + return nil, fmt.Errorf("error on get secrets list: %w", err) + } + defer res.Body.Close() + if lipOut.Items == nil { + return nil, nil + } + + listNames := make([]string, 0) + for _, v := range *lipOut.Items { + if path == "" || strings.HasPrefix(*v.ItemName, path) { + listNames = append(listNames, *v.ItemName) } - jwt, err := a.secretKeyRef(ctx, tokenRef) - if err != nil { - return "", err + } + return listNames, nil +} + +func (a *akeylessBase) getK8SServiceAccountJWT(ctx context.Context, kubernetesAuth *esv1beta1.AkeylessKubernetesAuth) (string, error) { + if kubernetesAuth != nil { + if kubernetesAuth.ServiceAccountRef != nil { + // Kubernetes =v1.24: fetch token via TokenRequest API + jwt, err = a.getJWTfromServiceAccountToken(ctx, *kubernetesAuth.ServiceAccountRef, nil, 600) + if err != nil { + return "", err + } + return jwt, nil + } else if kubernetesAuth.SecretRef != nil { + tokenRef := kubernetesAuth.SecretRef + if tokenRef.Key == "" { + tokenRef = kubernetesAuth.SecretRef.DeepCopy() + tokenRef.Key = "token" + } + jwt, err := a.secretKeyRef(ctx, tokenRef) + if err != nil { + return "", err + } + return jwt, nil } - return jwt, nil } return readK8SServiceAccountJWT() } @@ -282,7 +316,7 @@ func (a *akeylessBase) getJWTFromServiceAccount(ctx context.Context, serviceAcco Namespace: a.namespace, Name: serviceAccountRef.Name, } - if (a.store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind) && + if (a.storeKind == esv1beta1.ClusterSecretStoreKind) && (serviceAccountRef.Namespace != nil) { ref.Namespace = *serviceAccountRef.Namespace } @@ -314,7 +348,7 @@ func (a *akeylessBase) secretKeyRef(ctx context.Context, secretRef *esmeta.Secre Namespace: a.namespace, Name: secretRef.Name, } - if (a.store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind) && + if (a.storeKind == esv1beta1.ClusterSecretStoreKind) && (secretRef.Namespace != nil) { ref.Namespace = *secretRef.Namespace } @@ -347,7 +381,7 @@ func (a *akeylessBase) getJWTfromServiceAccountToken(ctx context.Context, servic ExpirationSeconds: &expirationSeconds, }, } - if (a.store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind) && + if (a.storeKind == esv1beta1.ClusterSecretStoreKind) && (serviceAccountRef.Namespace != nil) { tokenRequest.Namespace = *serviceAccountRef.Namespace } diff --git a/pkg/provider/akeyless/fake/fake.go b/pkg/provider/akeyless/fake/fake.go index e26676b732d..3d9ea29e521 100644 --- a/pkg/provider/akeyless/fake/fake.go +++ b/pkg/provider/akeyless/fake/fake.go @@ -25,10 +25,14 @@ func (mc *AkeylessMockClient) TokenFromSecretRef(ctx context.Context) (string, e return "newToken", nil } -func (mc *AkeylessMockClient) GetSecretByType(secretName, token string, version int32) (string, error) { +func (mc *AkeylessMockClient) GetSecretByType(_ context.Context, secretName, token string, version int32) (string, error) { return mc.getSecret(secretName, token, version) } +func (mc *AkeylessMockClient) ListSecrets(ctx context.Context, path, tag, token string) ([]string, error) { + return nil, nil +} + func (mc *AkeylessMockClient) WithValue(in *Input, out *Output) { if mc != nil { mc.getSecret = func(secretName, token string, version int32) (string, error) { diff --git a/pkg/provider/akeyless/utils.go b/pkg/provider/akeyless/utils.go index 9449875fc06..af678998738 100644 --- a/pkg/provider/akeyless/utils.go +++ b/pkg/provider/akeyless/utils.go @@ -14,6 +14,7 @@ limitations under the License. package akeyless import ( + "encoding/base64" "fmt" "io" "net/http" @@ -107,3 +108,12 @@ func sendReq(url string) string { body, _ := io.ReadAll(resp.Body) return string(body) } + +func base64decode(in []byte) ([]byte, error) { + out := make([]byte, len(in)) + l, err := base64.StdEncoding.Decode(out, in) + if err != nil { + return nil, err + } + return out[:l], nil +} From fdf9bda1d503d04af4766a4620b742d6404c061b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Mi=C5=A1en=C4=8D=C3=ADk?= Date: Thu, 9 Mar 2023 21:37:06 +0100 Subject: [PATCH 47/62] Fix ExternalSecret key in documentation (#2105) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix ExternalSecret key in documentation Signed-off-by: Šimon Mišenčík * Add comment into snippsets Signed-off-by: Simon Misencik --------- Signed-off-by: Šimon Mišenčík Signed-off-by: Simon Misencik --- docs/provider/hashicorp-vault.md | 2 +- docs/snippets/full-cluster-secret-store.yaml | 1 + docs/snippets/full-secret-store.yaml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/provider/hashicorp-vault.md b/docs/provider/hashicorp-vault.md index 9e0b3c62460..60e14d3300b 100644 --- a/docs/provider/hashicorp-vault.md +++ b/docs/provider/hashicorp-vault.md @@ -70,7 +70,7 @@ spec: data: - secretKey: foobar remoteRef: - key: secret/foo + key: foo property: my-value --- # will create a secret with: diff --git a/docs/snippets/full-cluster-secret-store.yaml b/docs/snippets/full-cluster-secret-store.yaml index 6a837caf9d0..e982c14af0b 100644 --- a/docs/snippets/full-cluster-secret-store.yaml +++ b/docs/snippets/full-cluster-secret-store.yaml @@ -40,6 +40,7 @@ spec: vault: server: "https://vault.acme.org" # Path is the mount path of the Vault KV backend endpoint + # Used as a path prefix for the external secret key path: "secret" # Version is the Vault KV secret engine version. # This can be either "v1" or "v2", defaults to "v2" diff --git a/docs/snippets/full-secret-store.yaml b/docs/snippets/full-secret-store.yaml index 4cf3cd43044..dacb717bda8 100644 --- a/docs/snippets/full-secret-store.yaml +++ b/docs/snippets/full-secret-store.yaml @@ -45,6 +45,7 @@ spec: vault: server: "https://vault.acme.org" # Path is the mount path of the Vault KV backend endpoint + # Used as a path prefix for the external secret key path: "secret" # Version is the Vault KV secret engine version. # This can be either "v1" or "v2", defaults to "v2" From da9689ccfd49be0c161d32b399672f4e0babfb49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20G=C3=B3mez?= <1637983+sebagomez@users.noreply.github.com> Date: Fri, 10 Mar 2023 12:23:39 -0500 Subject: [PATCH 48/62] Included metadataPolicy: Fetch in AWS ParameterStore (#2069) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * metadata fetch now working in parameterstore Signed-off-by: Sebastián Gómez * Little refactory and some tests added Tags from secretmanager and from parameterstore are not the same structure, thus, the function TagsToJSONString has now two versions (SecretTagsToSJONString & ParametersTagsToJSONString) Signed-off-by: Sebastián Gómez * New test cases Signed-off-by: Sebastián Gómez * Refactored to lift some code smells Signed-off-by: Sebastián Gómez * Constant for error message added (code smell) Signed-off-by: Sebastián Gómez * L&F Signed-off-by: Sebastián Gómez * Lint issue Signed-off-by: Sebastián Gómez * fix: fmt Signed-off-by: Moritz Johner --------- Signed-off-by: Sebastián Gómez Signed-off-by: Sebastián Gómez <1637983+sebagomez@users.noreply.github.com> Signed-off-by: Moritz Johner Co-authored-by: Moritz Johner --- .../aws/parameterstore/parameterstore.go | 42 +++++++++++-- .../aws/parameterstore/parameterstore_test.go | 63 ++++++++++++++++++- .../aws/secretsmanager/secretsmanager.go | 16 +---- .../aws/secretsmanager/secretsmanager_test.go | 7 ++- pkg/provider/aws/util/provider.go | 32 ++++++++++ 5 files changed, 136 insertions(+), 24 deletions(-) diff --git a/pkg/provider/aws/parameterstore/parameterstore.go b/pkg/provider/aws/parameterstore/parameterstore.go index 1367460afa7..35e5bf21ffe 100644 --- a/pkg/provider/aws/parameterstore/parameterstore.go +++ b/pkg/provider/aws/parameterstore/parameterstore.go @@ -324,10 +324,13 @@ func (pm *ParameterStore) fetchAndSet(ctx context.Context, data map[string][]byt // GetSecret returns a single secret from the provider. func (pm *ParameterStore) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) { - out, err := pm.client.GetParameterWithContext(ctx, &ssm.GetParameterInput{ - Name: &ref.Key, - WithDecryption: aws.Bool(true), - }) + var out *ssm.GetParameterOutput + var err error + if ref.MetadataPolicy == esv1beta1.ExternalSecretMetadataPolicyFetch { + out, err = pm.getParameterTags(ctx, ref) + } else { + out, err = pm.getParameterValue(ctx, ref) + } metrics.ObserveAPICall(metrics.ProviderAWSPS, metrics.CallAWSPSGetParameter, err) nsf := esv1beta1.NoSecretError{} var nf *ssm.ParameterNotFound @@ -358,6 +361,37 @@ func (pm *ParameterStore) GetSecret(ctx context.Context, ref esv1beta1.ExternalS return []byte(val.String()), nil } +func (pm *ParameterStore) getParameterTags(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (*ssm.GetParameterOutput, error) { + param := ssm.GetParameterOutput{ + Parameter: &ssm.Parameter{ + Name: &ref.Key, + }, + } + tags, err := pm.getTagsByName(ctx, ¶m) + if err != nil { + return nil, err + } + json, err := util.ParameterTagsToJSONString(tags) + if err != nil { + return nil, err + } + out := &ssm.GetParameterOutput{ + Parameter: &ssm.Parameter{ + Value: &json, + }, + } + return out, nil +} + +func (pm *ParameterStore) getParameterValue(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (*ssm.GetParameterOutput, error) { + out, err := pm.client.GetParameterWithContext(ctx, &ssm.GetParameterInput{ + Name: &ref.Key, + WithDecryption: aws.Bool(true), + }) + + return out, err +} + // GetSecretMap returns multiple k/v pairs from the provider. func (pm *ParameterStore) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) { data, err := pm.GetSecret(ctx, ref) diff --git a/pkg/provider/aws/parameterstore/parameterstore_test.go b/pkg/provider/aws/parameterstore/parameterstore_test.go index ee31b85f009..a62c6c4d876 100644 --- a/pkg/provider/aws/parameterstore/parameterstore_test.go +++ b/pkg/provider/aws/parameterstore/parameterstore_test.go @@ -28,6 +28,12 @@ import ( esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" fakeps "github.com/external-secrets/external-secrets/pkg/provider/aws/parameterstore/fake" + "github.com/external-secrets/external-secrets/pkg/provider/aws/util" +) + +const ( + errInvalidProperty = "key INVALPROP does not exist in secret" + invalidProp = "INVALPROP" ) type parameterstoreTestCase struct { @@ -481,8 +487,8 @@ func TestGetSecret(t *testing.T) { // bad case: extract property failure due to invalid json setPropertyFail := func(pstc *parameterstoreTestCase) { pstc.apiOutput.Parameter.Value = aws.String(`------`) - pstc.remoteRef.Property = "INVALPROP" - pstc.expectError = "key INVALPROP does not exist in secret" + pstc.remoteRef.Property = invalidProp + pstc.expectError = errInvalidProperty } // bad case: parameter.Value may be nil but binary is set @@ -498,6 +504,38 @@ func TestGetSecret(t *testing.T) { pstc.expectError = "oh no" } + // good case: metadata returned + setMetadataString := func(pstc *parameterstoreTestCase) { + pstc.remoteRef.MetadataPolicy = esv1beta1.ExternalSecretMetadataPolicyFetch + output := ssm.ListTagsForResourceOutput{ + TagList: getTagSlice(), + } + pstc.fakeClient.ListTagsForResourceWithContextFn = fakeps.NewListTagsForResourceWithContextFn(&output, nil) + pstc.expectedSecret, _ = util.ParameterTagsToJSONString(getTagSlice()) + } + + // good case: metadata property returned + setMetadataProperty := func(pstc *parameterstoreTestCase) { + pstc.remoteRef.MetadataPolicy = esv1beta1.ExternalSecretMetadataPolicyFetch + output := ssm.ListTagsForResourceOutput{ + TagList: getTagSlice(), + } + pstc.fakeClient.ListTagsForResourceWithContextFn = fakeps.NewListTagsForResourceWithContextFn(&output, nil) + pstc.remoteRef.Property = "tagname2" + pstc.expectedSecret = "tagvalue2" + } + + // bad case: metadata property not found + setMetadataMissingProperty := func(pstc *parameterstoreTestCase) { + pstc.remoteRef.MetadataPolicy = esv1beta1.ExternalSecretMetadataPolicyFetch + output := ssm.ListTagsForResourceOutput{ + TagList: getTagSlice(), + } + pstc.fakeClient.ListTagsForResourceWithContextFn = fakeps.NewListTagsForResourceWithContextFn(&output, nil) + pstc.remoteRef.Property = invalidProp + pstc.expectError = errInvalidProperty + } + successCases := []*parameterstoreTestCase{ makeValidParameterStoreTestCaseCustom(setSecretString), makeValidParameterStoreTestCaseCustom(setExtractProperty), @@ -507,6 +545,9 @@ func TestGetSecret(t *testing.T) { makeValidParameterStoreTestCaseCustom(setAPIError), makeValidParameterStoreTestCaseCustom(setExtractPropertyWithDot), makeValidParameterStoreTestCaseCustom(setParameterValueNotFound), + makeValidParameterStoreTestCaseCustom(setMetadataString), + makeValidParameterStoreTestCaseCustom(setMetadataProperty), + makeValidParameterStoreTestCaseCustom(setMetadataMissingProperty), } ps := ParameterStore{} @@ -595,3 +636,21 @@ func ErrorContains(out error, want string) bool { } return strings.Contains(out.Error(), want) } + +func getTagSlice() []*ssm.Tag { + tagKey1 := "tagname1" + tagValue1 := "tagvalue1" + tagKey2 := "tagname2" + tagValue2 := "tagvalue2" + + return []*ssm.Tag{ + { + Key: &tagKey1, + Value: &tagValue1, + }, + { + Key: &tagKey2, + Value: &tagValue2, + }, + } +} diff --git a/pkg/provider/aws/secretsmanager/secretsmanager.go b/pkg/provider/aws/secretsmanager/secretsmanager.go index cd376c5e1e3..bfc1b911c5e 100644 --- a/pkg/provider/aws/secretsmanager/secretsmanager.go +++ b/pkg/provider/aws/secretsmanager/secretsmanager.go @@ -110,7 +110,7 @@ func (sm *SecretsManager) fetch(ctx context.Context, ref esv1beta1.ExternalSecre } log.Info("found metadata secret", "key", ref.Key, "output", descOutput) - jsonTags, err := TagsToJSONString(descOutput.Tags) + jsonTags, err := util.SecretTagsToJSONString(descOutput.Tags) if err != nil { return nil, err } @@ -150,20 +150,6 @@ func (sm *SecretsManager) fetch(ctx context.Context, ref esv1beta1.ExternalSecre return secretOut, nil } -func TagsToJSONString(tags []*awssm.Tag) (string, error) { - tagMap := make(map[string]string, len(tags)) - for _, tag := range tags { - tagMap[*tag.Key] = *tag.Value - } - - byteArr, err := json.Marshal(tagMap) - if err != nil { - return "", err - } - - return string(byteArr), nil -} - func (sm *SecretsManager) DeleteSecret(ctx context.Context, remoteRef esv1beta1.PushRemoteRef) error { secretName := remoteRef.GetRemoteKey() secretValue := awssm.GetSecretValueInput{ diff --git a/pkg/provider/aws/secretsmanager/secretsmanager_test.go b/pkg/provider/aws/secretsmanager/secretsmanager_test.go index e326e537bd3..59c1deba9d5 100644 --- a/pkg/provider/aws/secretsmanager/secretsmanager_test.go +++ b/pkg/provider/aws/secretsmanager/secretsmanager_test.go @@ -29,6 +29,7 @@ import ( esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" fakesm "github.com/external-secrets/external-secrets/pkg/provider/aws/secretsmanager/fake" + "github.com/external-secrets/external-secrets/pkg/provider/aws/util" ) type secretsManagerTestCase struct { @@ -187,7 +188,7 @@ func TestSecretsManagerGetSecret(t *testing.T) { Tags: getTagSlice(), } smtc.fakeClient.DescribeSecretWithContextFn = fakesm.NewDescribeSecretWithContextFn(describeSecretOutput, nil) - jsonTags, _ := TagsToJSONString(getTagSlice()) + jsonTags, _ := util.SecretTagsToJSONString(getTagSlice()) smtc.apiOutput.SecretString = &jsonTags smtc.expectedSecret = jsonTags } @@ -199,7 +200,7 @@ func TestSecretsManagerGetSecret(t *testing.T) { } smtc.fakeClient.DescribeSecretWithContextFn = fakesm.NewDescribeSecretWithContextFn(describeSecretOutput, nil) smtc.remoteRef.Property = tagname2 - jsonTags, _ := TagsToJSONString(getTagSlice()) + jsonTags, _ := util.SecretTagsToJSONString(getTagSlice()) smtc.apiOutput.SecretString = &jsonTags smtc.expectedSecret = tagvalue2 } @@ -211,7 +212,7 @@ func TestSecretsManagerGetSecret(t *testing.T) { } smtc.fakeClient.DescribeSecretWithContextFn = fakesm.NewDescribeSecretWithContextFn(describeSecretOutput, nil) smtc.remoteRef.Property = "fail" - jsonTags, _ := TagsToJSONString(getTagSlice()) + jsonTags, _ := util.SecretTagsToJSONString(getTagSlice()) smtc.apiOutput.SecretString = &jsonTags smtc.expectError = "key fail does not exist in secret /baz" } diff --git a/pkg/provider/aws/util/provider.go b/pkg/provider/aws/util/provider.go index 0b04597b2b2..a378715e6f6 100644 --- a/pkg/provider/aws/util/provider.go +++ b/pkg/provider/aws/util/provider.go @@ -14,8 +14,12 @@ limitations under the License. package util import ( + "encoding/json" "fmt" + awssm "github.com/aws/aws-sdk-go/service/secretsmanager" + "github.com/aws/aws-sdk-go/service/ssm" + esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" ) @@ -59,3 +63,31 @@ func IsReferentSpec(prov esv1beta1.AWSAuth) bool { return false } + +func SecretTagsToJSONString(tags []*awssm.Tag) (string, error) { + tagMap := make(map[string]string, len(tags)) + for _, tag := range tags { + tagMap[*tag.Key] = *tag.Value + } + + byteArr, err := json.Marshal(tagMap) + if err != nil { + return "", err + } + + return string(byteArr), nil +} + +func ParameterTagsToJSONString(tags []*ssm.Tag) (string, error) { + tagMap := make(map[string]string, len(tags)) + for _, tag := range tags { + tagMap[*tag.Key] = *tag.Value + } + + byteArr, err := json.Marshal(tagMap) + if err != nil { + return "", err + } + + return string(byteArr), nil +} From c20fc5b8b334a295c58556d03a6af6726b870ee6 Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Sat, 11 Mar 2023 13:08:31 +0100 Subject: [PATCH 49/62] fix: support parsing PEM from multiple blocks (#2110) Before this PR it was required that the first PEM block contains the certificate. This PR parses all PEM blocks and returns the first certificate found. Signed-off-by: Moritz Johner --- pkg/provider/azure/keyvault/keyvault.go | 28 +++++++++++++++----- pkg/provider/azure/keyvault/keyvault_test.go | 17 +++++++++++- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/pkg/provider/azure/keyvault/keyvault.go b/pkg/provider/azure/keyvault/keyvault.go index e1ca63b1313..44c2582182f 100644 --- a/pkg/provider/azure/keyvault/keyvault.go +++ b/pkg/provider/azure/keyvault/keyvault.go @@ -309,15 +309,31 @@ func (a *Azure) DeleteSecret(ctx context.Context, remoteRef esv1beta1.PushRemote } func getCertificateFromValue(value []byte) (*x509.Certificate, error) { + // 1st: try decode pkcs12 _, localCert, err := pkcs12.Decode(value, "") - if err != nil { - pemBlock, _ := pem.Decode(value) - if pemBlock == nil { - return x509.ParseCertificate(value) + if err == nil { + return localCert, nil + } + + // 2nd: try DER + localCert, err = x509.ParseCertificate(value) + if err == nil { + return localCert, nil + } + + // 3nd: parse PEM blocks + for { + block, rest := pem.Decode(value) + value = rest + if block == nil { + break + } + cert, err := x509.ParseCertificate(block.Bytes) + if err == nil { + return cert, nil } - return x509.ParseCertificate(pemBlock.Bytes) } - return localCert, err + return nil, fmt.Errorf("could not parse certificate value as PKCS#12, DER or PEM") } func getKeyFromValue(value []byte) (interface{}, error) { diff --git a/pkg/provider/azure/keyvault/keyvault_test.go b/pkg/provider/azure/keyvault/keyvault_test.go index f4123270765..73d0890d242 100644 --- a/pkg/provider/azure/keyvault/keyvault_test.go +++ b/pkg/provider/azure/keyvault/keyvault_test.go @@ -606,6 +606,20 @@ func TestAzureKeyVaultPushSecret(t *testing.T) { } } + certPEMWithGarbageSuccess := func(smtc *secretManagerTestCase) { + pemCert, _ := base64.StdEncoding.DecodeString("LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBNWNXTTdWYnd2dGtxWXVLd1lrVUhlSXRMQnd2eUd2ekhzODQwbDZpT00rZXZneEVXCmcydFAvb3NYeG1Rb1ZOdDJLUXRScEwweTh4K3JhWHhRRm5VTlJEc3pHSEkyWTdmWnVVRWd0M2FQQVhmUUlMNm0KazdJaWQ0VmZUdlpLTFhNbnB6dEduNVlaTVBxak0yU3k3ZWY5ZjJMNkxuamNwRkRNZFBqN25vd0pxcTdMb3kxcAo2aU1xeHNyRGY1RXloRHdGUVhiZHRQM0pPNmpjSDY4UUVsVkE0eVR5RHR4WXpxSS9mb0pIM2tGZStHSmJwS0FNCnlNQXRwVkphS2F6VGVnTCtWZnc1MFV2czFLT3A3L1ZxZXVCd2FpZDhtWkhYWDFRUE44RE9VUmJRbkhoVUp1Y3UKZlIyNVdlbHhqWUtOMGdGWFE1bHo5MXY1TmVlTnhQWkhRbkZ2NVFJREFRQUJBb0lCQUNQR2FuYlp2b280amR6dgpwcjdtT0krUVFKSk1UZG5kMmNvcEpROG44MXdwaXE1Qmp0dlBiWmtZVnc5UXNPYmxkTFJYU3RMM2ttTkFYeFFCCmd3YThHdUN3eHZmYmNKUitINncwYzcrYytnOGtkSWRrcDlML1BWYVdzWXc5MUxiVzR5bXFsUWhyK21naDNoODIKWXBXZ05Wd01NUi9qT1pkcjdTbVpTclFZNGJodFN6eFlDOE5Vc0hwL1JaR3FqejdILzRyR1B5dEpTMjFVYVMzegpabXBLdHcrRm81ZVF5UW5lUVUyL2dmNkxTV3JUZjI5Y3NXSEVlMUpRWHZzYlA1enAxbGEzRjBXczEvOUNyT0VNCnFsbUNWNFRXWXR1Nno1a2k2Y1c1enkybEVLSnpCYTVqT0ZqRGtqREFzRm1IZmNydXlMbVVqZUU2MWlPZjAycXQKV1Z5MkZZRUNnWUVBNmRRdFgxTDNmaVpKdFUzd0lkVytxVkZSeEFwMUd6RG5TaEJBQmg0SDA5eHFhMzc2RXovSgpYUmdrV0xLZTU0VUdnZi9ZTzJDTkRkSzVGZmw1MHNrN1hDeGJPRzZITTNSRytxZjQ0MXUzQWd6L0ppa3QyOFBMCmZ2dUJYRG91a1hQUUVvWHR1cHNHaFJLRUxleWhZTHNJSzZNWndJQnFBQThGV200cWc1b2RPazBDZ1lFQSs0N2sKaXNHMWRxaFdnUk1Fc1ZBVG9SeW9ITDBXYVFpbkhXUWQ4ZFBDZ1BDNzJqbmZQdmZ2THZnUEVEeEMxTk41VEJNUQpwOHliS2EvOEZOVzV0VkpQdXdsSGlveURKdHZVVFQ1UVZtVmtOa21LZllZR1h0dVlqQUVtaVJWL0JSRVZQSG0yCnYvTjBLRHA2YVRTQXAxdm10czZoQ0I0ZGNSeXkyNnNTdG5XcUova0NnWUEwRHlBMjYrTGNQQ3dHNko1QStqU2oKdjg0amhteUNMRVlpVURIZzZzaTFXNHA1K21BMDd1dW5CVnY2UDNKdmUwZHlwQUtCWGNLcHhET2U5OWN1bmN6UQpmYk9sZ2I0cUw0WXFBa0hBWk1mKzllUE1uRGh3aUV3RExuMmppZlNhUDUyZ3NoNjJnQk5ZaDBIVWM2Mk9PclhiCitVa2ZlYmVmNGJoQVpPeWtOaWl4dFFLQmdFNm1MRm9kbWlpUkZRcWg4Wk9tWDV5OW91bnBUSHBtVkNsaVJlSjMKdkpZbnJmUGFxQ3U5eExCQXFpVC9VajNNS0Y1YWo1aUc1ZlF3cTNXd0pMSEdIRnR6MlVRK0RqczErN2h5eFJkZAo5K2pwTVQxeGk4aFlpK2NwN094ckpoMWxhK2hPZlk2aUJTMFdxM0w5RVVSQi9XNG1TRDZMZTlVRGpnQVVDbk8xCmNnK3hBb0dCQU9YVktjTzFpS3UrZWNCZUxFMVV0M2JUcUFCL2tCcFRkdVZZbTh3Mld0b1BUQ2tqUTZNc2o5ZWcKRjJ0R0pwbUV0djZ6NnMzbmo1TmhSWlYyWDh0WjMxWHViVkdVQUt4aGprSnlPQnBuczk3bTlxZUMxRHlFcDlMaQp6RnFpQ1VMWVp1c1JObzVTWVRCcHBCbmFPN1ArODhFMnFmV3Fob0h6b1dYNWk1a2dpK0tXCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQpNSUlGcHpDQ0E0K2dBd0lCQWdJVU1IYVQ2bWRvL3dlK24rdDRQdkdCWWlHQ0lxNHdEUVlKS29aSWh2Y05BUUVMCkJRQXdZekVMTUFrR0ExVUVCaE1DUVZVeEV6QVJCZ05WQkFnTUNsTnZiV1V0VTNSaGRHVXhJVEFmQmdOVkJBb00KR0VsdWRHVnlibVYwSUZkcFpHZHBkSE1nVUhSNUlFeDBaREVjTUJvR0ExVUVBd3dUWVc1dmRHaGxjaTFtYjI4dApZbUZ5TG1OdmJUQWVGdzB5TWpBMk1Ea3hOelExTXpaYUZ3MHlNekEyTURreE56UTFNelphTUdNeEN6QUpCZ05WCkJBWVRBa0ZWTVJNd0VRWURWUVFJREFwVGIyMWxMVk4wWVhSbE1TRXdId1lEVlFRS0RCaEpiblJsY201bGRDQlgKYVdSbmFYUnpJRkIwZVNCTWRHUXhIREFhQmdOVkJBTU1FMkZ1YjNSb1pYSXRabTl2TFdKaGNpNWpiMjB3Z2dJaQpNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUNEd0F3Z2dJS0FvSUNBUUNaSE80bzZKbXlPWmRmQXQ3RFdqR2tHdzdECjVVSFNQR2V0Mk44NnJwRll3K2U4Zy93UngwZ2Qwc0ZPaXpQQURHY3J6ZnVhOWd2RXA0VnNXb2FHbmN3UXhqdnMKK2daK1pkNlJFTzR0Szc0VEZmMWlmYm5qMFBxNjhDZUJRaWhvMWwzcDNlMEMvMnplSTIzYnZWRHZlMm13VXE5aAo2OFExRVJnVjFNS2liR1NTWmpOQ0M3ZERhUFpqSms1YjBZVlRXcURFYnpkRFZ4dmVVTDVScUZnL0RKQTMzVnE2ClRUM0NlOUYwSHBKK294K2krOHFMZllOamRMUlA2ZWxLS01OZ2lYYTUxb3Z0OTIxeFJFRnZYRXYvTUtqWTlhNkoKaTZ3SEUrNDZnb2xWOFdqbitsTEZESlR4elhBRDdqdjc1c2h2NFhHM3RZWkNieHEzM2dibW96c0VQZ3lTRGtCMgpuc3NLSFBBYUlTT2lqYzQ4Ykl4cGw1aHBST1lGRW5SQ1p4Wm5YUDY3S2VRdVVmV0JKaFVnYWltc0JRK3p6cFB6CmY1VG40Z1RMZFpZdjVONVdVdnYySXVBeUJLYWtGYUdWWE8xaWdhQ3lUL1EzQXBBNmRseEo1VW44SzY4dS9KSGEKZllmeXp4MFZ1aGZOc25rYlpMVkhGbEdkcXdya1NLQlkrNXkvVlpaZHgvYUhzVlp3VTd2RGNlaGxlWlFNNGV2cgpubTFGN3ZOcUhwVCtwR0p6TVVlVDRmTFRaWm0wa2tWN2V5eURkTDAxRFl0V0JNUzNjRG9RdU5vWElBMCtDeFZPCjh3MXAvcG1xdlBUN3JqWndqcGJFTFJKdzFrOEd6M1NhSm9lamhQc1gvcTczRllnQXNPT0RwTXJuK3ZpU2U0ZnIKZkdFZmZRL2FyVFROaitQVG93SURBUUFCbzFNd1VUQWRCZ05WSFE0RUZnUVViT0JNeGsyeVJDZEdTeHhGRjMwVApGTkRYR0tzd0h3WURWUjBqQkJnd0ZvQVViT0JNeGsyeVJDZEdTeHhGRjMwVEZORFhHS3N3RHdZRFZSMFRBUUgvCkJBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQUF3bnVLcTk4TkNoVDJVM1NkUjRBVXptTE4xQlcKMDRyMDEwN045SnVvS28ycnI4aGdtZkZndDA4K3RTQ2M0eWo2UjUrcmNYbnV6anhGS2liVWJxZ3Bab3dKUkhhMgoxdDVCYnBMMXlnMmxmcmZ4SG92L0Y4dFZzU21BOHd5aDZVaVdSd0U5a3ZQV1JuS25UdWt2NXp6c3FTbE5TaWxtCjQ5elE3U1dObCtJQUZ5L3N3WnJ0SlExMFZUOXM0blBlRzNvV1FNb3RPUFArbGxTaXluS0xacVE0Z1NLUmkzZmUKUExpV3B0OVhmWG9HVUNFajdxNXBoYmxMUGdkS1VDcmhHUDFuMmpZbVhzY1dMTXlrQW5hMjBjaGxycVZZbkNhOApKVXA0TGZ0RkRwODlZVG9YT0ZIbkZtbk5DdmNJckRmRnlEZmhsNFVNRnBLME9VS3FUVHhXYUs5dXFPSXBhcklzCktZd3NwK2ZMZVdMYlE2a0dmbW5PNWlEUmQrb09ock5Zb29UWlZLOWZRUjVyRDJlNEIrZWEwcnpRRlhBQVVqSjUKT1hhYnhiRHJRK09NZWp3YzRIcXFzeHp0SmdEMmFQMmVLMi9MNVBXUHVnMEUrMWc4QUJaZlZib2gvTTNNSGdiegpQZ2FUcWd1ekdGZGtHM0VYdStPaEdiVTAvKzc3Vk1uWmkySVFabi9hd0dVYTdYK01QMEJEdmpWWTVrVnBNWjFoCmMyQ2xEamd4TnNMR3Rpa080Y1diNXNRUlIyR1lNM2RNazUwVlFjdEo1UnFzUnM2cE9DWERYRTNSZVZRajRoTkIKZVd2YURXUTJLbXlPYWk1NWRiRHJsSitudTgzT21DcDU5UnpQNWs1OFphRFhubEMzOFV3VHQwcTFENyt6RjB0cwoxRzkzMnVFQkhXWUh1T0E9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K") + smtc.setValue = pemCert + smtc.pushRef = fakeRef{ + key: certName, + } + smtc.certOutput = keyvault.CertificateBundle{ + X509Thumbprint: pointer.String("123"), + Tags: map[string]*string{ + "managed-by": pointer.String("external-secrets"), + }, + } + } + certDERSuccess := func(smtc *secretManagerTestCase) { derCert, _ := base64.StdEncoding.DecodeString("MIIFpzCCA4+gAwIBAgIUMHaT6mdo/we+n+t4PvGBYiGCIq4wDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEcMBoGA1UEAwwTYW5vdGhlci1mb28tYmFyLmNvbTAeFw0yMjA2MDkxNzQ1MzZaFw0yMzA2MDkxNzQ1MzZaMGMxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxHDAaBgNVBAMME2Fub3RoZXItZm9vLWJhci5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCZHO4o6JmyOZdfAt7DWjGkGw7D5UHSPGet2N86rpFYw+e8g/wRx0gd0sFOizPADGcrzfua9gvEp4VsWoaGncwQxjvs+gZ+Zd6REO4tK74TFf1ifbnj0Pq68CeBQiho1l3p3e0C/2zeI23bvVDve2mwUq9h68Q1ERgV1MKibGSSZjNCC7dDaPZjJk5b0YVTWqDEbzdDVxveUL5RqFg/DJA33Vq6TT3Ce9F0HpJ+ox+i+8qLfYNjdLRP6elKKMNgiXa51ovt921xREFvXEv/MKjY9a6Ji6wHE+46golV8Wjn+lLFDJTxzXAD7jv75shv4XG3tYZCbxq33gbmozsEPgySDkB2nssKHPAaISOijc48bIxpl5hpROYFEnRCZxZnXP67KeQuUfWBJhUgaimsBQ+zzpPzf5Tn4gTLdZYv5N5WUvv2IuAyBKakFaGVXO1igaCyT/Q3ApA6dlxJ5Un8K68u/JHafYfyzx0VuhfNsnkbZLVHFlGdqwrkSKBY+5y/VZZdx/aHsVZwU7vDcehleZQM4evrnm1F7vNqHpT+pGJzMUeT4fLTZZm0kkV7eyyDdL01DYtWBMS3cDoQuNoXIA0+CxVO8w1p/pmqvPT7rjZwjpbELRJw1k8Gz3SaJoejhPsX/q73FYgAsOODpMrn+viSe4frfGEffQ/arTTNj+PTowIDAQABo1MwUTAdBgNVHQ4EFgQUbOBMxk2yRCdGSxxFF30TFNDXGKswHwYDVR0jBBgwFoAUbOBMxk2yRCdGSxxFF30TFNDXGKswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAAwnuKq98NChT2U3SdR4AUzmLN1BW04r0107N9JuoKo2rr8hgmfFgt08+tSCc4yj6R5+rcXnuzjxFKibUbqgpZowJRHa21t5BbpL1yg2lfrfxHov/F8tVsSmA8wyh6UiWRwE9kvPWRnKnTukv5zzsqSlNSilm49zQ7SWNl+IAFy/swZrtJQ10VT9s4nPeG3oWQMotOPP+llSiynKLZqQ4gSKRi3fePLiWpt9XfXoGUCEj7q5phblLPgdKUCrhGP1n2jYmXscWLMykAna20chlrqVYnCa8JUp4LftFDp89YToXOFHnFmnNCvcIrDfFyDfhl4UMFpK0OUKqTTxWaK9uqOIparIsKYwsp+fLeWLbQ6kGfmnO5iDRd+oOhrNYooTZVK9fQR5rD2e4B+ea0rzQFXAAUjJ5OXabxbDrQ+OMejwc4HqqsxztJgD2aP2eK2/L5PWPug0E+1g8ABZfVboh/M3MHgbzPgaTqguzGFdkG3EXu+OhGbU0/+77VMnZi2IQZn/awGUa7X+MP0BDvjVY5kVpMZ1hc2ClDjgxNsLGtikO4cWb5sQRR2GYM3dMk50VQctJ5RqsRs6pOCXDXE3ReVQj4hNBeWvaDWQ2KmyOai55dbDrlJ+nu83OmCp59RzP5k58ZaDXnlC38UwTt0q1D7+zF0ts1G932uEBHWYHuOA=") smtc.setValue = derCert @@ -683,7 +697,7 @@ func TestAzureKeyVaultPushSecret(t *testing.T) { smtc.certOutput = keyvault.CertificateBundle{ X509Thumbprint: pointer.String("123"), } - smtc.expectError = "value from secret is not a valid certificate: x509: malformed certificate" + smtc.expectError = "value from secret is not a valid certificate: could not parse certificate value as PKCS#12, DER or PEM" } certNoPermissions := func(smtc *secretManagerTestCase) { @@ -705,6 +719,7 @@ func TestAzureKeyVaultPushSecret(t *testing.T) { successCases := []*secretManagerTestCase{ makeValidSecretManagerTestCaseCustom(certP12Success), makeValidSecretManagerTestCaseCustom(certPEMSuccess), + makeValidSecretManagerTestCaseCustom(certPEMWithGarbageSuccess), makeValidSecretManagerTestCaseCustom(certDERSuccess), makeValidSecretManagerTestCaseCustom(certImportCertificateError), makeValidSecretManagerTestCaseCustom(certFingerprintMatches), From 9edc957aef6319f746ac260a350581da582eb28a Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Sun, 12 Mar 2023 16:34:08 +0100 Subject: [PATCH 50/62] feat: rely on controller backoff/retry instead of static requeue (#2100) * feat: rely on controller backoff/retry instead of static requeue interval Fixes #2088 more context in: https://github.com/external-secrets/external-secrets/pull/934 Signed-off-by: Moritz Johner * fix: respect refreshInterval on delete/retain Signed-off-by: Moritz Johner --------- Signed-off-by: Moritz Johner --- .../externalsecret/externalsecret_controller.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pkg/controllers/externalsecret/externalsecret_controller.go b/pkg/controllers/externalsecret/externalsecret_controller.go index 57989eba9d1..56617ca8e0a 100644 --- a/pkg/controllers/externalsecret/externalsecret_controller.go +++ b/pkg/controllers/externalsecret/externalsecret_controller.go @@ -46,7 +46,6 @@ import ( ) const ( - requeueAfter = time.Second * 30 fieldOwnerTemplate = "externalsecrets.external-secrets.io/%v" errGetES = "could not get ExternalSecret" errConvert = "could not apply conversion strategy to keys: %v" @@ -192,7 +191,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu conditionSynced := NewExternalSecretCondition(esv1beta1.ExternalSecretReady, v1.ConditionFalse, esv1beta1.ConditionReasonSecretSyncedError, errGetSecretData) SetExternalSecretCondition(&externalSecret, *conditionSynced) syncCallsError.With(resourceLabels).Inc() - return ctrl.Result{RequeueAfter: requeueAfter}, nil + return ctrl.Result{}, err } // if no data was found we can delete the secret if needed. @@ -209,7 +208,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu conditionSynced := NewExternalSecretCondition(esv1beta1.ExternalSecretReady, v1.ConditionFalse, esv1beta1.ConditionReasonSecretSyncedError, errDeleteSecret) SetExternalSecretCondition(&externalSecret, *conditionSynced) syncCallsError.With(resourceLabels).Inc() - return ctrl.Result{RequeueAfter: requeueAfter}, nil + return ctrl.Result{}, err } err = r.Delete(ctx, secret) if err != nil && !apierrors.IsNotFound(err) { @@ -222,14 +221,14 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu conditionSynced := NewExternalSecretCondition(esv1beta1.ExternalSecretReady, v1.ConditionTrue, esv1beta1.ConditionReasonSecretDeleted, "secret deleted due to DeletionPolicy") SetExternalSecretCondition(&externalSecret, *conditionSynced) - return ctrl.Result{RequeueAfter: requeueAfter}, nil + return ctrl.Result{RequeueAfter: refreshInt}, err case esv1beta1.DeletionPolicyMerge: // noop, handled below // In case provider secrets don't exist the kubernetes secret will be kept as-is. case esv1beta1.DeletionPolicyRetain: - return ctrl.Result{RequeueAfter: requeueAfter}, nil + return ctrl.Result{RequeueAfter: refreshInt}, nil } } From 1eca34c94d6169e0c0f415caaf8dda5acb829e00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristi=C3=A1n=20Le=C5=A1ko?= Date: Mon, 13 Mar 2023 16:31:10 +0100 Subject: [PATCH 51/62] feat: Vault dynamic secrets Generator (#2074) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Vault dynamic secrets Generator Signed-off-by: Kristián Leško * Update pkg/provider/vault/vault.go Signed-off-by: Moritz Johner Signed-off-by: Moritz Johner * feat: Vault dynamic secrets Generator Signed-off-by: Kristián Leško * Update pkg/provider/vault/vault.go Signed-off-by: Moritz Johner Signed-off-by: Moritz Johner * fix: linter Signed-off-by: Moritz Johner --------- Signed-off-by: Kristián Leško Signed-off-by: Moritz Johner Signed-off-by: Moritz Johner Co-authored-by: Moritz Johner Co-authored-by: Moritz Johner --- apis/generators/v1alpha1/generator_vault.go | 54 +++ apis/generators/v1alpha1/register.go | 9 + .../v1alpha1/zz_generated.deepcopy.go | 85 ++++ ...ternal-secrets.io_vaultdynamicsecrets.yaml | 439 ++++++++++++++++++ .../external-secrets/templates/rbac.yaml | 7 +- deploy/crds/bundle.yaml | 322 +++++++++++++ .../clusterexternalsecret/suite_test.go | 2 - pkg/generator/register/register.go | 3 +- pkg/generator/vault/vault.go | 117 +++++ pkg/generator/vault/vault_test.go | 145 ++++++ pkg/provider/register/register.go | 2 +- pkg/provider/vault/fake/vault.go | 26 ++ pkg/provider/vault/util/vault.go | 91 ++++ pkg/provider/vault/vault.go | 198 ++++---- pkg/provider/vault/vault_test.go | 102 ++-- pkg/utils/utils.go | 3 +- 16 files changed, 1438 insertions(+), 167 deletions(-) create mode 100644 apis/generators/v1alpha1/generator_vault.go create mode 100644 config/crds/bases/generators.external-secrets.io_vaultdynamicsecrets.yaml create mode 100644 pkg/generator/vault/vault.go create mode 100644 pkg/generator/vault/vault_test.go create mode 100644 pkg/provider/vault/util/vault.go diff --git a/apis/generators/v1alpha1/generator_vault.go b/apis/generators/v1alpha1/generator_vault.go new file mode 100644 index 00000000000..5005b30db5b --- /dev/null +++ b/apis/generators/v1alpha1/generator_vault.go @@ -0,0 +1,54 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" +) + +type VaultDynamicSecretSpec struct { + // Vault API method to use (GET/POST/other) + Method string `json:"method,omitempty"` + + // Parameters to pass to Vault write (for non-GET methods) + Parameters *apiextensions.JSON `json:"parameters,omitempty"` + + // Vault provider common spec + Provider *esv1beta1.VaultProvider `json:"provider"` + + // Vault path to obtain the dynamic secret from + Path string `json:"path"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:storageversion +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Namespaced,categories={vaultdynamicsecret},shortName=vaultdynamicsecret +type VaultDynamicSecret struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec VaultDynamicSecretSpec `json:"spec,omitempty"` +} + +// +kubebuilder:object:root=true +type VaultDynamicSecretList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VaultDynamicSecret `json:"items"` +} diff --git a/apis/generators/v1alpha1/register.go b/apis/generators/v1alpha1/register.go index f19e677220c..cef819f4c28 100644 --- a/apis/generators/v1alpha1/register.go +++ b/apis/generators/v1alpha1/register.go @@ -76,10 +76,19 @@ var ( FakeGroupVersionKind = SchemeGroupVersion.WithKind(FakeKind) ) +// Vault type metadata. +var ( + VaultDynamicSecretKind = reflect.TypeOf(VaultDynamicSecret{}).Name() + VaultDynamicSecretGroupKind = schema.GroupKind{Group: Group, Kind: VaultDynamicSecretKind}.String() + VaultDynamicSecretKindAPIVersion = VaultDynamicSecretKind + "." + SchemeGroupVersion.String() + VaultDynamicSecretGroupVersionKind = SchemeGroupVersion.WithKind(VaultDynamicSecretKind) +) + func init() { SchemeBuilder.Register(&ECRAuthorizationToken{}, &ECRAuthorizationToken{}) SchemeBuilder.Register(&GCRAccessToken{}, &GCRAccessTokenList{}) SchemeBuilder.Register(&ACRAccessToken{}, &ACRAccessTokenList{}) SchemeBuilder.Register(&Fake{}, &FakeList{}) + SchemeBuilder.Register(&VaultDynamicSecret{}, &VaultDynamicSecretList{}) SchemeBuilder.Register(&Password{}, &PasswordList{}) } diff --git a/apis/generators/v1alpha1/zz_generated.deepcopy.go b/apis/generators/v1alpha1/zz_generated.deepcopy.go index c974ce27c10..03d621373db 100644 --- a/apis/generators/v1alpha1/zz_generated.deepcopy.go +++ b/apis/generators/v1alpha1/zz_generated.deepcopy.go @@ -20,7 +20,9 @@ limitations under the License. package v1alpha1 import ( + "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" "github.com/external-secrets/external-secrets/apis/meta/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -635,3 +637,86 @@ func (in *PasswordSpec) DeepCopy() *PasswordSpec { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VaultDynamicSecret) DeepCopyInto(out *VaultDynamicSecret) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultDynamicSecret. +func (in *VaultDynamicSecret) DeepCopy() *VaultDynamicSecret { + if in == nil { + return nil + } + out := new(VaultDynamicSecret) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VaultDynamicSecret) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VaultDynamicSecretList) DeepCopyInto(out *VaultDynamicSecretList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VaultDynamicSecret, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultDynamicSecretList. +func (in *VaultDynamicSecretList) DeepCopy() *VaultDynamicSecretList { + if in == nil { + return nil + } + out := new(VaultDynamicSecretList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VaultDynamicSecretList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VaultDynamicSecretSpec) DeepCopyInto(out *VaultDynamicSecretSpec) { + *out = *in + if in.Parameters != nil { + in, out := &in.Parameters, &out.Parameters + *out = new(apiextensionsv1.JSON) + (*in).DeepCopyInto(*out) + } + if in.Provider != nil { + in, out := &in.Provider, &out.Provider + *out = new(v1beta1.VaultProvider) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultDynamicSecretSpec. +func (in *VaultDynamicSecretSpec) DeepCopy() *VaultDynamicSecretSpec { + if in == nil { + return nil + } + out := new(VaultDynamicSecretSpec) + in.DeepCopyInto(out) + return out +} diff --git a/config/crds/bases/generators.external-secrets.io_vaultdynamicsecrets.yaml b/config/crds/bases/generators.external-secrets.io_vaultdynamicsecrets.yaml new file mode 100644 index 00000000000..3fb8a2e1855 --- /dev/null +++ b/config/crds/bases/generators.external-secrets.io_vaultdynamicsecrets.yaml @@ -0,0 +1,439 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.3 + creationTimestamp: null + name: vaultdynamicsecrets.generators.external-secrets.io +spec: + group: generators.external-secrets.io + names: + categories: + - vaultdynamicsecret + kind: VaultDynamicSecret + listKind: VaultDynamicSecretList + plural: vaultdynamicsecrets + shortNames: + - vaultdynamicsecret + singular: vaultdynamicsecret + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + method: + description: Vault API method to use (GET/POST/other) + type: string + parameters: + description: Parameters to pass to Vault write (for non-GET methods) + x-kubernetes-preserve-unknown-fields: true + path: + description: Vault path to obtain the dynamic secret from + type: string + provider: + description: Vault provider common spec + properties: + auth: + description: Auth configures how secret-manager authenticates + with the Vault server. + properties: + appRole: + description: AppRole authenticates with Vault using the App + Role auth mechanism, with the role and secret stored in + a Kubernetes Secret resource. + properties: + path: + default: approle + description: 'Path where the App Role authentication backend + is mounted in Vault, e.g: "approle"' + type: string + roleId: + description: RoleID configured in the App Role authentication + backend when setting up the authentication backend in + Vault. + type: string + secretRef: + description: Reference to a key in a Secret that contains + the App Role secret used to authenticate with Vault. + The `key` field must be specified and denotes which + entry within the Secret resource is used as the app + role secret. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + required: + - path + - roleId + - secretRef + type: object + cert: + description: Cert authenticates with TLS Certificates by passing + client certificate, private key and ca certificate Cert + authentication method + properties: + clientCert: + description: ClientCert is a certificate to authenticate + using the Cert Vault authentication method + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + secretRef: + description: SecretRef to a key in a Secret resource containing + client private key to authenticate with Vault using + the Cert authentication method + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + type: object + jwt: + description: Jwt authenticates with Vault by passing role + and JWT token using the JWT/OIDC authentication method + properties: + kubernetesServiceAccountToken: + description: Optional ServiceAccountToken specifies the + Kubernetes service account for which to request a token + for with the `TokenRequest` API. + properties: + audiences: + description: 'Optional audiences field that will be + used to request a temporary Kubernetes service account + token for the service account referenced by `serviceAccountRef`. + Defaults to a single audience `vault` it not specified. + Deprecated: use serviceAccountRef.Audiences instead' + items: + type: string + type: array + expirationSeconds: + description: 'Optional expiration time in seconds + that will be used to request a temporary Kubernetes + service account token for the service account referenced + by `serviceAccountRef`. Deprecated: this will be + removed in the future. Defaults to 10 minutes.' + format: int64 + type: integer + serviceAccountRef: + description: Service account field containing the + name of a kubernetes ServiceAccount. + properties: + audiences: + description: Audience specifies the `aud` claim + for the service account token If the service + account uses a well-known annotation for e.g. + IRSA or GCP Workload Identity then this audiences + will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource + being referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. + cluster-scoped defaults to the namespace of + the referent. + type: string + required: + - name + type: object + required: + - serviceAccountRef + type: object + path: + default: jwt + description: 'Path where the JWT authentication backend + is mounted in Vault, e.g: "jwt"' + type: string + role: + description: Role is a JWT role to authenticate using + the JWT/OIDC Vault authentication method + type: string + secretRef: + description: Optional SecretRef that refers to a key in + a Secret resource containing JWT token to authenticate + with Vault using the JWT/OIDC authentication method. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + required: + - path + type: object + kubernetes: + description: Kubernetes authenticates with Vault by passing + the ServiceAccount token stored in the named Secret resource + to the Vault server. + properties: + mountPath: + default: kubernetes + description: 'Path where the Kubernetes authentication + backend is mounted in Vault, e.g: "kubernetes"' + type: string + role: + description: A required field containing the Vault Role + to assume. A Role binds a Kubernetes ServiceAccount + with a set of Vault policies. + type: string + secretRef: + description: Optional secret field containing a Kubernetes + ServiceAccount JWT used for authenticating with Vault. + If a name is specified without a key, `token` is the + default. If one is not specified, the one bound to the + controller will be used. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: Optional service account field containing + the name of a kubernetes ServiceAccount. If the service + account is specified, the service account secret token + JWT will be used for authenticating with Vault. If the + service account selector is not supplied, the secretRef + will be used instead. + properties: + audiences: + description: Audience specifies the `aud` claim for + the service account token If the service account + uses a well-known annotation for e.g. IRSA or GCP + Workload Identity then this audiences will be appended + to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource + being referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - mountPath + - role + type: object + ldap: + description: Ldap authenticates with Vault by passing username/password + pair using the LDAP authentication method + properties: + path: + default: ldap + description: 'Path where the LDAP authentication backend + is mounted in Vault, e.g: "ldap"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing + password for the LDAP user used to authenticate with + Vault using the LDAP authentication method + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a LDAP user name used to authenticate + using the LDAP Vault authentication method + type: string + required: + - path + - username + type: object + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting + a token. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this field + may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred + to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + type: object + caBundle: + description: PEM encoded CA bundle used to validate Vault server + certificate. Only used if the Server URL is using HTTPS protocol. + This parameter is ignored for plain HTTP protocol connection. + If not set the system root certificates are used to validate + the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate + Vault server certificate. + properties: + key: + description: The key where the CA certificate can be found + in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider + type. + type: string + namespace: + description: The namespace the Provider type is in. Can only + be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", + or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + forwardInconsistent: + description: ForwardInconsistent tells Vault to forward read-after-write + requests to the Vault leader instead of simply retrying within + a loop. This can increase performance if the option is enabled + serverside. https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header + type: boolean + namespace: + description: 'Name of the vault namespace. Namespaces is a set + of features within Vault Enterprise that allows Vault environments + to support Secure Multi-tenancy. e.g: "ns1". More about namespaces + can be found here https://www.vaultproject.io/docs/enterprise/namespaces' + type: string + path: + description: 'Path is the mount path of the Vault KV backend endpoint, + e.g: "secret". The v2 KV secret engine version specific "/data" + path suffix for fetching secrets from Vault is optional and + will be appended if not present in specified path.' + type: string + readYourWrites: + description: ReadYourWrites ensures isolated read-after-write + semantics by providing discovered cluster replication states + in each request. More information about eventual consistency + in Vault can be found here https://www.vaultproject.io/docs/enterprise/consistency + type: boolean + server: + description: 'Server is the connection address for the Vault server, + e.g: "https://vault.example.com:8200".' + type: string + version: + default: v2 + description: Version is the Vault KV secret engine version. This + can be either "v1" or "v2". Version defaults to "v2". + enum: + - v1 + - v2 + type: string + required: + - auth + - server + type: object + required: + - path + - provider + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/deploy/charts/external-secrets/templates/rbac.yaml b/deploy/charts/external-secrets/templates/rbac.yaml index 773282be30b..abb795a44ed 100644 --- a/deploy/charts/external-secrets/templates/rbac.yaml +++ b/deploy/charts/external-secrets/templates/rbac.yaml @@ -49,11 +49,12 @@ rules: - apiGroups: - "generators.external-secrets.io" resources: - - "fakes" - - "passwords" - "acraccesstokens" - - "gcraccesstokens" - "ecrauthorizationtokens" + - "fakes" + - "gcraccesstokens" + - "passwords" + - "vaultdynamicsecrets" verbs: - "get" - "list" diff --git a/deploy/crds/bundle.yaml b/deploy/crds/bundle.yaml index bae0a285034..0ed223e9a15 100644 --- a/deploy/crds/bundle.yaml +++ b/deploy/crds/bundle.yaml @@ -6866,3 +6866,325 @@ spec: name: kubernetes namespace: default path: /convert +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.3 + creationTimestamp: null + name: vaultdynamicsecrets.generators.external-secrets.io +spec: + group: generators.external-secrets.io + names: + categories: + - vaultdynamicsecret + kind: VaultDynamicSecret + listKind: VaultDynamicSecretList + plural: vaultdynamicsecrets + shortNames: + - vaultdynamicsecret + singular: vaultdynamicsecret + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + method: + description: Vault API method to use (GET/POST/other) + type: string + parameters: + description: Parameters to pass to Vault write (for non-GET methods) + x-kubernetes-preserve-unknown-fields: true + path: + description: Vault path to obtain the dynamic secret from + type: string + provider: + description: Vault provider common spec + properties: + auth: + description: Auth configures how secret-manager authenticates with the Vault server. + properties: + appRole: + description: AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource. + properties: + path: + default: approle + description: 'Path where the App Role authentication backend is mounted in Vault, e.g: "approle"' + type: string + roleId: + description: RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault. + type: string + secretRef: + description: Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The `key` field must be specified and denotes which entry within the Secret resource is used as the app role secret. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - path + - roleId + - secretRef + type: object + cert: + description: Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate Cert authentication method + properties: + clientCert: + description: ClientCert is a certificate to authenticate using the Cert Vault authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + secretRef: + description: SecretRef to a key in a Secret resource containing client private key to authenticate with Vault using the Cert authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + jwt: + description: Jwt authenticates with Vault by passing role and JWT token using the JWT/OIDC authentication method + properties: + kubernetesServiceAccountToken: + description: Optional ServiceAccountToken specifies the Kubernetes service account for which to request a token for with the `TokenRequest` API. + properties: + audiences: + description: 'Optional audiences field that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to a single audience `vault` it not specified. Deprecated: use serviceAccountRef.Audiences instead' + items: + type: string + type: array + expirationSeconds: + description: 'Optional expiration time in seconds that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Deprecated: this will be removed in the future. Defaults to 10 minutes.' + format: int64 + type: integer + serviceAccountRef: + description: Service account field containing the name of a kubernetes ServiceAccount. + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - serviceAccountRef + type: object + path: + default: jwt + description: 'Path where the JWT authentication backend is mounted in Vault, e.g: "jwt"' + type: string + role: + description: Role is a JWT role to authenticate using the JWT/OIDC Vault authentication method + type: string + secretRef: + description: Optional SecretRef that refers to a key in a Secret resource containing JWT token to authenticate with Vault using the JWT/OIDC authentication method. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - path + type: object + kubernetes: + description: Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server. + properties: + mountPath: + default: kubernetes + description: 'Path where the Kubernetes authentication backend is mounted in Vault, e.g: "kubernetes"' + type: string + role: + description: A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: Optional secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. If a name is specified without a key, `token` is the default. If one is not specified, the one bound to the controller will be used. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: Optional service account field containing the name of a kubernetes ServiceAccount. If the service account is specified, the service account secret token JWT will be used for authenticating with Vault. If the service account selector is not supplied, the secretRef will be used instead. + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - mountPath + - role + type: object + ldap: + description: Ldap authenticates with Vault by passing username/password pair using the LDAP authentication method + properties: + path: + default: ldap + description: 'Path where the LDAP authentication backend is mounted in Vault, e.g: "ldap"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the LDAP user used to authenticate with Vault using the LDAP authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a LDAP user name used to authenticate using the LDAP Vault authentication method + type: string + required: + - path + - username + type: object + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caBundle: + description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Vault server certificate. + properties: + key: + description: The key where the CA certificate can be found in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. Can only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + forwardInconsistent: + description: ForwardInconsistent tells Vault to forward read-after-write requests to the Vault leader instead of simply retrying within a loop. This can increase performance if the option is enabled serverside. https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header + type: boolean + namespace: + description: 'Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1". More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces' + type: string + path: + description: 'Path is the mount path of the Vault KV backend endpoint, e.g: "secret". The v2 KV secret engine version specific "/data" path suffix for fetching secrets from Vault is optional and will be appended if not present in specified path.' + type: string + readYourWrites: + description: ReadYourWrites ensures isolated read-after-write semantics by providing discovered cluster replication states in each request. More information about eventual consistency in Vault can be found here https://www.vaultproject.io/docs/enterprise/consistency + type: boolean + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + version: + default: v2 + description: Version is the Vault KV secret engine version. This can be either "v1" or "v2". Version defaults to "v2". + enum: + - v1 + - v2 + type: string + required: + - auth + - server + type: object + required: + - path + - provider + type: object + type: object + served: true + storage: true + subresources: + status: {} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: kubernetes + namespace: default + path: /convert diff --git a/pkg/controllers/clusterexternalsecret/suite_test.go b/pkg/controllers/clusterexternalsecret/suite_test.go index 4a67ca9bc35..4894eb8e868 100644 --- a/pkg/controllers/clusterexternalsecret/suite_test.go +++ b/pkg/controllers/clusterexternalsecret/suite_test.go @@ -16,7 +16,6 @@ package clusterexternalsecret import ( "context" - "math/rand" "path/filepath" "testing" "time" @@ -50,7 +49,6 @@ func TestAPIs(t *testing.T) { } var _ = BeforeSuite(func() { - rand.Seed(time.Now().UnixNano()) log := zap.New(zap.WriteTo(GinkgoWriter), zap.Level(zapcore.DebugLevel)) logf.SetLogger(log) diff --git a/pkg/generator/register/register.go b/pkg/generator/register/register.go index 9d71b97b53d..6c8d7a4226f 100644 --- a/pkg/generator/register/register.go +++ b/pkg/generator/register/register.go @@ -12,14 +12,15 @@ See the License for the specific language governing permissions and limitations under the License. */ +//nolint:revive package register // packages imported here are registered to the controller schema. -//nolint:revive import ( _ "github.com/external-secrets/external-secrets/pkg/generator/acr" _ "github.com/external-secrets/external-secrets/pkg/generator/ecr" _ "github.com/external-secrets/external-secrets/pkg/generator/fake" _ "github.com/external-secrets/external-secrets/pkg/generator/gcr" _ "github.com/external-secrets/external-secrets/pkg/generator/password" + _ "github.com/external-secrets/external-secrets/pkg/generator/vault" ) diff --git a/pkg/generator/vault/vault.go b/pkg/generator/vault/vault.go new file mode 100644 index 00000000000..db7ed6509e0 --- /dev/null +++ b/pkg/generator/vault/vault.go @@ -0,0 +1,117 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package vaultdynamic + +import ( + "context" + "encoding/json" + "fmt" + + vault "github.com/hashicorp/vault/api" + apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/client-go/kubernetes" + typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config" + "sigs.k8s.io/yaml" + + genv1alpha1 "github.com/external-secrets/external-secrets/apis/generators/v1alpha1" + provider "github.com/external-secrets/external-secrets/pkg/provider/vault" +) + +type Generator struct{} + +const ( + errNoSpec = "no config spec provided" + errParseSpec = "unable to parse spec: %w" + errVaultClient = "unable to setup Vault client: %w" + errGetSecret = "unable to get dynamic secret: %w" +) + +func (g *Generator) Generate(ctx context.Context, jsonSpec *apiextensions.JSON, kube client.Client, namespace string) (map[string][]byte, error) { + c := &provider.Connector{NewVaultClient: provider.NewVaultClient} + + // controller-runtime/client does not support TokenRequest or other subresource APIs + // so we need to construct our own client and use it to fetch tokens + // (for Kubernetes service account token auth) + restCfg, err := ctrlcfg.GetConfig() + if err != nil { + return nil, err + } + clientset, err := kubernetes.NewForConfig(restCfg) + if err != nil { + return nil, err + } + + return g.generate(ctx, c, jsonSpec, kube, clientset.CoreV1(), namespace) +} + +func (g *Generator) generate(ctx context.Context, c *provider.Connector, jsonSpec *apiextensions.JSON, kube client.Client, corev1 typedcorev1.CoreV1Interface, namespace string) (map[string][]byte, error) { + if jsonSpec == nil { + return nil, fmt.Errorf(errNoSpec) + } + res, err := parseSpec(jsonSpec.Raw) + if err != nil { + return nil, fmt.Errorf(errParseSpec, err) + } + if res == nil || res.Spec.Provider == nil { + return nil, fmt.Errorf("no Vault provider config in spec") + } + cl, err := c.NewGeneratorClient(ctx, kube, corev1, res.Spec.Provider, namespace) + if err != nil { + return nil, fmt.Errorf(errVaultClient, err) + } + + var result *vault.Secret + if res.Spec.Method == "" || res.Spec.Method == "GET" { + result, err = cl.Logical().ReadWithDataWithContext(ctx, res.Spec.Path, nil) + } else if res.Spec.Method == "LIST" { + result, err = cl.Logical().ListWithContext(ctx, res.Spec.Path) + } else if res.Spec.Method == "DELETE" { + result, err = cl.Logical().DeleteWithContext(ctx, res.Spec.Path) + } else { + params := make(map[string]interface{}) + err = json.Unmarshal(res.Spec.Parameters.Raw, ¶ms) + if err != nil { + return nil, err + } + result, err = cl.Logical().WriteWithContext(ctx, res.Spec.Path, params) + } + if err != nil { + return nil, err + } + if result == nil { + return nil, fmt.Errorf(errGetSecret, fmt.Errorf("empty response from Vault")) + } + + response := make(map[string][]byte) + for k := range result.Data { + response[k], err = provider.GetTypedKey(result.Data, k) + if err != nil { + return nil, err + } + } + return response, nil +} + +func parseSpec(data []byte) (*genv1alpha1.VaultDynamicSecret, error) { + var spec genv1alpha1.VaultDynamicSecret + err := yaml.Unmarshal(data, &spec) + return &spec, err +} + +func init() { + genv1alpha1.Register(genv1alpha1.VaultDynamicSecretKind, &Generator{}) +} diff --git a/pkg/generator/vault/vault_test.go b/pkg/generator/vault/vault_test.go new file mode 100644 index 00000000000..713da84de66 --- /dev/null +++ b/pkg/generator/vault/vault_test.go @@ -0,0 +1,145 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package vaultdynamic + +import ( + "context" + "errors" + "fmt" + "testing" + + "github.com/google/go-cmp/cmp" + corev1 "k8s.io/api/core/v1" + apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" + kclient "sigs.k8s.io/controller-runtime/pkg/client" + clientfake "sigs.k8s.io/controller-runtime/pkg/client/fake" + + utilfake "github.com/external-secrets/external-secrets/pkg/provider/util/fake" + provider "github.com/external-secrets/external-secrets/pkg/provider/vault" + "github.com/external-secrets/external-secrets/pkg/provider/vault/fake" +) + +type args struct { + jsonSpec *apiextensions.JSON + kube kclient.Client + corev1 typedcorev1.CoreV1Interface +} + +type want struct { + val map[string][]byte + err error +} + +type testCase struct { + reason string + args args + want want +} + +func TestVaultDynamicSecretGenerator(t *testing.T) { + cases := map[string]testCase{ + "NilSpec": { + reason: "Raise an error with empty spec.", + args: args{ + jsonSpec: nil, + }, + want: want{ + err: errors.New("no config spec provided"), + }, + }, + "InvalidSpec": { + reason: "Raise an error with invalid spec.", + args: args{ + jsonSpec: &apiextensions.JSON{ + Raw: []byte(``), + }, + }, + want: want{ + err: errors.New("no Vault provider config in spec"), + }, + }, + "MissingRoleName": { + reason: "Raise error if incomplete k8s auth config is provided.", + args: args{ + corev1: utilfake.NewCreateTokenMock().WithToken("ok"), + jsonSpec: &apiextensions.JSON{ + Raw: []byte(`apiVersion: generators.external-secrets.io/v1alpha1 +kind: VaultDynamicSecret +spec: + provider: + auth: + kubernetes: + serviceAccountRef: + name: "testing" + method: GET + path: "github/token/example"`), + }, + kube: clientfake.NewClientBuilder().Build(), + }, + want: want{ + err: fmt.Errorf("unable to setup Vault client: no role name was provided"), + }, + }, + "EmptyVaultResponse": { + reason: "Fail on empty response from Vault.", + args: args{ + corev1: utilfake.NewCreateTokenMock().WithToken("ok"), + jsonSpec: &apiextensions.JSON{ + Raw: []byte(`apiVersion: generators.external-secrets.io/v1alpha1 +kind: VaultDynamicSecret +spec: + provider: + auth: + kubernetes: + role: test + serviceAccountRef: + name: "testing" + method: GET + path: "github/token/example"`), + }, + kube: clientfake.NewClientBuilder().WithObjects(&corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: "testing", + Namespace: "testing", + }, + Secrets: []corev1.ObjectReference{ + { + Name: "test", + }, + }, + }).Build(), + }, + want: want{ + err: fmt.Errorf("unable to get dynamic secret: empty response from Vault"), + }, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + c := &provider.Connector{NewVaultClient: fake.ClientWithLoginMock} + gen := &Generator{} + val, err := gen.generate(context.Background(), c, tc.args.jsonSpec, tc.args.kube, tc.args.corev1, "testing") + if diff := cmp.Diff(tc.want.err.Error(), err.Error()); diff != "" { + t.Errorf("\n%s\nvault.GetSecret(...): -want error, +got error:\n%s", tc.reason, diff) + } + if diff := cmp.Diff(tc.want.val, val); diff != "" { + t.Errorf("\n%s\nvault.GetSecret(...): -want val, +got val:\n%s", tc.reason, diff) + } + }) + } +} diff --git a/pkg/provider/register/register.go b/pkg/provider/register/register.go index cd9c0fb0b19..cdd279de7b3 100644 --- a/pkg/provider/register/register.go +++ b/pkg/provider/register/register.go @@ -12,10 +12,10 @@ See the License for the specific language governing permissions and limitations under the License. */ +//nolint:revive package register // packages imported here are registered to the controller schema. -//nolint:revive import ( _ "github.com/external-secrets/external-secrets/pkg/provider/akeyless" _ "github.com/external-secrets/external-secrets/pkg/provider/alibaba" diff --git a/pkg/provider/vault/fake/vault.go b/pkg/provider/vault/fake/vault.go index ad6587e815a..e4709430ab6 100644 --- a/pkg/provider/vault/fake/vault.go +++ b/pkg/provider/vault/fake/vault.go @@ -18,6 +18,8 @@ import ( "context" vault "github.com/hashicorp/vault/api" + + util "github.com/external-secrets/external-secrets/pkg/provider/vault/util" ) type LoginFn func(ctx context.Context, authMethod vault.AuthMethod) (*vault.Secret, error) @@ -235,3 +237,27 @@ func (c *VaultClient) SetNamespace(namespace string) { func (c *VaultClient) AddHeader(key, value string) { c.MockAddHeader(key, value) } + +func ClientWithLoginMock(c *vault.Config) (util.Client, error) { + cl := VaultClient{ + MockAuthToken: NewAuthTokenFn(), + MockSetToken: NewSetTokenFn(), + MockToken: NewTokenFn(""), + MockAuth: NewVaultAuth(), + MockLogical: NewVaultLogical(), + } + auth := cl.Auth() + token := cl.AuthToken() + logical := cl.Logical() + out := util.VClient{ + SetTokenFunc: cl.SetToken, + TokenFunc: cl.Token, + ClearTokenFunc: cl.ClearToken, + AuthField: auth, + AuthTokenField: token, + LogicalField: logical, + SetNamespaceFunc: cl.SetNamespace, + AddHeaderFunc: cl.AddHeader, + } + return out, nil +} diff --git a/pkg/provider/vault/util/vault.go b/pkg/provider/vault/util/vault.go new file mode 100644 index 00000000000..47fa93b49ed --- /dev/null +++ b/pkg/provider/vault/util/vault.go @@ -0,0 +1,91 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "context" + + vault "github.com/hashicorp/vault/api" +) + +type Auth interface { + Login(ctx context.Context, authMethod vault.AuthMethod) (*vault.Secret, error) +} + +type Token interface { + RevokeSelfWithContext(ctx context.Context, token string) error + LookupSelfWithContext(ctx context.Context) (*vault.Secret, error) +} + +type Logical interface { + ReadWithDataWithContext(ctx context.Context, path string, data map[string][]string) (*vault.Secret, error) + ListWithContext(ctx context.Context, path string) (*vault.Secret, error) + WriteWithContext(ctx context.Context, path string, data map[string]interface{}) (*vault.Secret, error) + DeleteWithContext(ctx context.Context, path string) (*vault.Secret, error) +} + +type Client interface { + SetToken(v string) + Token() string + ClearToken() + Auth() Auth + Logical() Logical + AuthToken() Token + SetNamespace(namespace string) + AddHeader(key, value string) +} + +type VClient struct { + SetTokenFunc func(v string) + TokenFunc func() string + ClearTokenFunc func() + AuthField Auth + LogicalField Logical + AuthTokenField Token + SetNamespaceFunc func(namespace string) + AddHeaderFunc func(key, value string) +} + +func (v VClient) AddHeader(key, value string) { + v.AddHeaderFunc(key, value) +} + +func (v VClient) SetNamespace(namespace string) { + v.SetNamespaceFunc(namespace) +} + +func (v VClient) ClearToken() { + v.ClearTokenFunc() +} + +func (v VClient) Token() string { + return v.TokenFunc() +} + +func (v VClient) SetToken(token string) { + v.SetTokenFunc(token) +} + +func (v VClient) Auth() Auth { + return v.AuthField +} + +func (v VClient) AuthToken() Token { + return v.AuthTokenField +} + +func (v VClient) Logical() Logical { + return v.LogicalField +} diff --git a/pkg/provider/vault/vault.go b/pkg/provider/vault/vault.go index 8a4bca2e260..114fba7c84b 100644 --- a/pkg/provider/vault/vault.go +++ b/pkg/provider/vault/vault.go @@ -24,6 +24,7 @@ import ( "fmt" "net/http" "os" + "reflect" "strconv" "strings" @@ -50,15 +51,16 @@ import ( "github.com/external-secrets/external-secrets/pkg/feature" "github.com/external-secrets/external-secrets/pkg/find" "github.com/external-secrets/external-secrets/pkg/provider/metrics" + "github.com/external-secrets/external-secrets/pkg/provider/vault/util" "github.com/external-secrets/external-secrets/pkg/utils" ) var ( - _ esv1beta1.Provider = &connector{} + _ esv1beta1.Provider = &Connector{} _ esv1beta1.SecretsClient = &client{} enableCache bool logger = ctrl.Log.WithName("provider").WithName("vault") - clientCache *cache.Cache[Client] + clientCache *cache.Cache[util.Client] ) const ( @@ -76,7 +78,7 @@ const ( errDataField = "failed to find data field" errJSONUnmarshall = "failed to unmarshall JSON" errPathInvalid = "provided Path isn't a valid kv v2 path" - errSecretFormat = "secret data not in expected format" + errSecretFormat = "secret data for property %s not in expected format: %s" errUnexpectedKey = "unexpected key in data: %s" errVaultToken = "cannot parse Vault authentication token: %w" errVaultRequest = "error from Vault request: %w" @@ -119,92 +121,22 @@ const ( // https://github.com/external-secrets/external-secrets/issues/644 var _ esv1beta1.SecretsClient = &client{} -var _ esv1beta1.Provider = &connector{} - -type Auth interface { - Login(ctx context.Context, authMethod vault.AuthMethod) (*vault.Secret, error) -} - -type Token interface { - RevokeSelfWithContext(ctx context.Context, token string) error - LookupSelfWithContext(ctx context.Context) (*vault.Secret, error) -} - -type Logical interface { - ReadWithDataWithContext(ctx context.Context, path string, data map[string][]string) (*vault.Secret, error) - ListWithContext(ctx context.Context, path string) (*vault.Secret, error) - WriteWithContext(ctx context.Context, path string, data map[string]interface{}) (*vault.Secret, error) - DeleteWithContext(ctx context.Context, path string) (*vault.Secret, error) -} - -type Client interface { - SetToken(v string) - Token() string - ClearToken() - Auth() Auth - Logical() Logical - AuthToken() Token - SetNamespace(namespace string) - AddHeader(key, value string) -} - -type VClient struct { - setToken func(v string) - token func() string - clearToken func() - auth Auth - logical Logical - authToken Token - setNamespace func(namespace string) - addHeader func(key, value string) -} - -func (v VClient) AddHeader(key, value string) { - v.addHeader(key, value) -} - -func (v VClient) SetNamespace(namespace string) { - v.setNamespace(namespace) -} - -func (v VClient) ClearToken() { - v.clearToken() -} - -func (v VClient) Token() string { - return v.token() -} - -func (v VClient) SetToken(token string) { - v.setToken(token) -} - -func (v VClient) Auth() Auth { - return v.auth -} - -func (v VClient) AuthToken() Token { - return v.authToken -} - -func (v VClient) Logical() Logical { - return v.logical -} +var _ esv1beta1.Provider = &Connector{} type client struct { kube kclient.Client store *esv1beta1.VaultProvider log logr.Logger corev1 typedcorev1.CoreV1Interface - client Client - auth Auth - logical Logical - token Token + client util.Client + auth util.Auth + logical util.Logical + token util.Token namespace string storeKind string } -func newVaultClient(c *vault.Config) (Client, error) { +func NewVaultClient(c *vault.Config) (util.Client, error) { cl, err := vault.NewClient(c) if err != nil { return nil, err @@ -212,20 +144,20 @@ func newVaultClient(c *vault.Config) (Client, error) { auth := cl.Auth() logical := cl.Logical() token := cl.Auth().Token() - out := VClient{ - setToken: cl.SetToken, - token: cl.Token, - clearToken: cl.ClearToken, - auth: auth, - authToken: token, - logical: logical, - setNamespace: cl.SetNamespace, - addHeader: cl.AddHeader, - } - return out, nil + out := util.VClient{ + SetTokenFunc: cl.SetToken, + TokenFunc: cl.Token, + ClearTokenFunc: cl.ClearToken, + AuthField: auth, + AuthTokenField: token, + LogicalField: logical, + SetNamespaceFunc: cl.SetNamespace, + AddHeaderFunc: cl.AddHeader, + } + return &out, nil } -func getVaultClient(c *connector, store esv1beta1.GenericStore, cfg *vault.Config) (Client, error) { +func getVaultClient(c *Connector, store esv1beta1.GenericStore, cfg *vault.Config) (util.Client, error) { isStaticToken := store.GetSpec().Provider.Vault.Auth.TokenSecretRef != nil useCache := enableCache && !isStaticToken @@ -241,7 +173,7 @@ func getVaultClient(c *connector, store esv1beta1.GenericStore, cfg *vault.Confi } } - client, err := c.newVaultClient(cfg) + client, err := c.NewVaultClient(cfg) if err != nil { return nil, fmt.Errorf(errVaultClient, err) } @@ -252,16 +184,15 @@ func getVaultClient(c *connector, store esv1beta1.GenericStore, cfg *vault.Confi return client, nil } -type connector struct { - newVaultClient func(c *vault.Config) (Client, error) +type Connector struct { + NewVaultClient func(c *vault.Config) (util.Client, error) } // Capabilities return the provider supported capabilities (ReadOnly, WriteOnly, ReadWrite). -func (c *connector) Capabilities() esv1beta1.SecretStoreCapabilities { +func (c *Connector) Capabilities() esv1beta1.SecretStoreCapabilities { return esv1beta1.SecretStoreReadWrite } - -func (c *connector) NewClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, namespace string) (esv1beta1.SecretsClient, error) { +func (c *Connector) NewClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, namespace string) (esv1beta1.SecretsClient, error) { // controller-runtime/client does not support TokenRequest or other subresource APIs // so we need to construct our own client and use it to fetch tokens // (for Kubernetes service account token auth) @@ -277,32 +208,63 @@ func (c *connector) NewClient(ctx context.Context, store esv1beta1.GenericStore, return c.newClient(ctx, store, kube, clientset.CoreV1(), namespace) } -func (c *connector) newClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, corev1 typedcorev1.CoreV1Interface, namespace string) (esv1beta1.SecretsClient, error) { +func (c *Connector) newClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, corev1 typedcorev1.CoreV1Interface, namespace string) (esv1beta1.SecretsClient, error) { storeSpec := store.GetSpec() if storeSpec == nil || storeSpec.Provider == nil || storeSpec.Provider.Vault == nil { return nil, errors.New(errVaultStore) } vaultSpec := storeSpec.Provider.Vault + vStore, cfg, err := c.prepareConfig(kube, corev1, vaultSpec, namespace, store.GetObjectKind().GroupVersionKind().Kind) + if err != nil { + return nil, err + } + + client, err := getVaultClient(c, store, cfg) + if err != nil { + return nil, fmt.Errorf(errVaultClient, err) + } + + return c.initClient(ctx, vStore, client, cfg, vaultSpec) +} + +func (c *Connector) NewGeneratorClient(ctx context.Context, kube kclient.Client, corev1 typedcorev1.CoreV1Interface, vaultSpec *esv1beta1.VaultProvider, namespace string) (util.Client, error) { + vStore, cfg, err := c.prepareConfig(kube, corev1, vaultSpec, namespace, "Generator") + if err != nil { + return nil, err + } + + client, err := c.NewVaultClient(cfg) + if err != nil { + return nil, err + } + + _, err = c.initClient(ctx, vStore, client, cfg, vaultSpec) + if err != nil { + return nil, err + } + + return client, nil +} + +func (c *Connector) prepareConfig(kube kclient.Client, corev1 typedcorev1.CoreV1Interface, vaultSpec *esv1beta1.VaultProvider, namespace, storeKind string) (*client, *vault.Config, error) { vStore := &client{ kube: kube, corev1: corev1, store: vaultSpec, log: logger, namespace: namespace, - storeKind: store.GetObjectKind().GroupVersionKind().Kind, + storeKind: storeKind, } cfg, err := vStore.newConfig() if err != nil { - return nil, err - } - - client, err := getVaultClient(c, store, cfg) - if err != nil { - return nil, fmt.Errorf(errVaultClient, err) + return nil, nil, err } + return vStore, cfg, nil +} +func (c *Connector) initClient(ctx context.Context, vStore *client, client util.Client, cfg *vault.Config, vaultSpec *esv1beta1.VaultProvider) (esv1beta1.SecretsClient, error) { if vaultSpec.Namespace != nil { client.SetNamespace(*vaultSpec.Namespace) } @@ -327,7 +289,7 @@ func (c *connector) newClient(ctx context.Context, store esv1beta1.GenericStore, return vStore, nil } -func (c *connector) ValidateStore(store esv1beta1.GenericStore) error { +func (c *Connector) ValidateStore(store esv1beta1.GenericStore) error { if store == nil { return fmt.Errorf(errInvalidStore) } @@ -669,7 +631,7 @@ func (v *client) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretData // actual keys to take precedence over gjson syntax // (2): extract key from secret with property if _, ok := data[ref.Property]; ok { - return getTypedKey(data, ref.Property) + return GetTypedKey(data, ref.Property) } // (3): extract key from secret using gjson @@ -696,7 +658,7 @@ func (v *client) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretD } byteMap := make(map[string][]byte, len(secretData)) for k := range secretData { - byteMap[k], err = getTypedKey(secretData, k) + byteMap[k], err = GetTypedKey(secretData, k) if err != nil { return nil, err } @@ -705,7 +667,7 @@ func (v *client) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretD return byteMap, nil } -func getTypedKey(data map[string]interface{}, key string) ([]byte, error) { +func GetTypedKey(data map[string]interface{}, key string) ([]byte, error) { v, ok := data[key] if !ok { return nil, fmt.Errorf(errUnexpectedKey, key) @@ -715,17 +677,23 @@ func getTypedKey(data map[string]interface{}, key string) ([]byte, error) { return []byte(t), nil case map[string]interface{}: return json.Marshal(t) + case []string: + return []byte(strings.Join(t, "\n")), nil case []byte: return t, nil // also covers int and float32 due to json.Marshal case float64: return []byte(strconv.FormatFloat(t, 'f', -1, 64)), nil + case json.Number: + return []byte(t.String()), nil + case []interface{}: + return json.Marshal(t) case bool: return []byte(strconv.FormatBool(t)), nil case nil: return []byte(nil), nil default: - return nil, errors.New(errSecretFormat) + return nil, fmt.Errorf(errSecretFormat, key, reflect.TypeOf(t)) } } @@ -1220,7 +1188,7 @@ func (v *client) serviceAccountToken(ctx context.Context, serviceAccountRef esme } // checkToken does a lookup and checks if the provided token exists. -func checkToken(ctx context.Context, token Token) (bool, error) { +func checkToken(ctx context.Context, token util.Token) (bool, error) { // https://www.vaultproject.io/api-docs/auth/token#lookup-a-token-self resp, err := token.LookupSelfWithContext(ctx) metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultLookupSelf, err) @@ -1238,7 +1206,7 @@ func checkToken(ctx context.Context, token Token) (bool, error) { return true, nil } -func revokeTokenIfValid(ctx context.Context, client Client) error { +func revokeTokenIfValid(ctx context.Context, client util.Client) error { valid, err := checkToken(ctx, client.AuthToken()) if err != nil { return fmt.Errorf(errVaultRevokeToken, err) @@ -1441,7 +1409,7 @@ func init() { fs.IntVar(&vaultTokenCacheSize, "experimental-vault-token-cache-size", 2<<17, "Maximum size of Vault token cache. When more tokens than Only used if --experimental-enable-vault-token-cache is set.") lateInit := func() { logger.Info("initializing vault cache with size=%d", vaultTokenCacheSize) - clientCache = cache.Must(vaultTokenCacheSize, func(client Client) { + clientCache = cache.Must(vaultTokenCacheSize, func(client util.Client) { err := revokeTokenIfValid(context.Background(), client) if err != nil { logger.Error(err, "unable to revoke cached token on eviction") @@ -1453,8 +1421,8 @@ func init() { Initialize: lateInit, }) - esv1beta1.Register(&connector{ - newVaultClient: newVaultClient, + esv1beta1.Register(&Connector{ + NewVaultClient: NewVaultClient, }, &esv1beta1.SecretStoreProvider{ Vault: &esv1beta1.VaultProvider{}, }) diff --git a/pkg/provider/vault/vault_test.go b/pkg/provider/vault/vault_test.go index 28e0bc03d88..a56c6d8d024 100644 --- a/pkg/provider/vault/vault_test.go +++ b/pkg/provider/vault/vault_test.go @@ -16,6 +16,7 @@ package vault import ( "context" + "encoding/json" "errors" "fmt" "reflect" @@ -35,6 +36,7 @@ import ( esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" utilfake "github.com/external-secrets/external-secrets/pkg/provider/util/fake" "github.com/external-secrets/external-secrets/pkg/provider/vault/fake" + "github.com/external-secrets/external-secrets/pkg/provider/vault/util" ) const ( @@ -172,7 +174,7 @@ func makeSecretStore(tweaks ...secretStoreTweakFn) *esv1beta1.SecretStore { } type args struct { - newClientFunc func(c *vault.Config) (Client, error) + newClientFunc func(c *vault.Config) (util.Client, error) store esv1beta1.GenericStore kube kclient.Client corev1 typedcorev1.CoreV1Interface @@ -189,30 +191,6 @@ type testCase struct { want want } -func clientWithLoginMock(c *vault.Config) (Client, error) { - cl := fake.VaultClient{ - MockAuthToken: fake.NewAuthTokenFn(), - MockSetToken: fake.NewSetTokenFn(), - MockToken: fake.NewTokenFn(""), - MockAuth: fake.NewVaultAuth(), - MockLogical: fake.NewVaultLogical(), - } - auth := cl.Auth() - token := cl.AuthToken() - logical := cl.Logical() - out := VClient{ - setToken: cl.SetToken, - token: cl.Token, - clearToken: cl.ClearToken, - auth: auth, - authToken: token, - logical: logical, - setNamespace: cl.SetNamespace, - addHeader: cl.AddHeader, - } - return out, nil -} - func TestNewVault(t *testing.T) { errBoom := errors.New("boom") secretClientKey := []byte(`-----BEGIN PRIVATE KEY----- @@ -258,7 +236,7 @@ MIIFkTCCA3mgAwIBAgIUBEUg3m/WqAsWHG4Q/II3IePFfuowDQYJKoZIhvcNAQELBQAwWDELMAkGA1UE "GetKubeServiceAccountError": { reason: "Should return error if fetching kubernetes secret fails.", args: args{ - newClientFunc: clientWithLoginMock, + newClientFunc: fake.ClientWithLoginMock, ns: "default", kube: clientfake.NewClientBuilder().Build(), store: makeSecretStore(), @@ -300,14 +278,14 @@ MIIFkTCCA3mgAwIBAgIUBEUg3m/WqAsWHG4Q/II3IePFfuowDQYJKoZIhvcNAQELBQAwWDELMAkGA1UE "tls.crt": clientCrt, }, }).Build(), - newClientFunc: clientWithLoginMock, + newClientFunc: fake.ClientWithLoginMock, }, want: want{ err: nil, }, }, "SuccessfulVaultStoreWithK8sCertSecret": { - reason: "Should return a Vault prodvider with the cert from k8s", + reason: "Should return a Vault provider with the cert from k8s", args: args{ store: makeValidSecretStoreWithK8sCerts(true), ns: "default", @@ -322,7 +300,7 @@ MIIFkTCCA3mgAwIBAgIUBEUg3m/WqAsWHG4Q/II3IePFfuowDQYJKoZIhvcNAQELBQAwWDELMAkGA1UE }, }).Build(), corev1: utilfake.NewCreateTokenMock().WithToken("ok"), - newClientFunc: clientWithLoginMock, + newClientFunc: fake.ClientWithLoginMock, }, want: want{ err: nil, @@ -351,7 +329,7 @@ MIIFkTCCA3mgAwIBAgIUBEUg3m/WqAsWHG4Q/II3IePFfuowDQYJKoZIhvcNAQELBQAwWDELMAkGA1UE }, Data: map[string][]byte{}, }).Build(), - newClientFunc: clientWithLoginMock, + newClientFunc: fake.ClientWithLoginMock, }, want: want{ err: fmt.Errorf(errVaultCert, errors.New(`cannot find secret data for key: "cert"`)), @@ -371,7 +349,7 @@ MIIFkTCCA3mgAwIBAgIUBEUg3m/WqAsWHG4Q/II3IePFfuowDQYJKoZIhvcNAQELBQAwWDELMAkGA1UE }, }).Build(), corev1: utilfake.NewCreateTokenMock().WithToken("ok"), - newClientFunc: clientWithLoginMock, + newClientFunc: fake.ClientWithLoginMock, }, want: want{ err: nil, @@ -398,7 +376,7 @@ MIIFkTCCA3mgAwIBAgIUBEUg3m/WqAsWHG4Q/II3IePFfuowDQYJKoZIhvcNAQELBQAwWDELMAkGA1UE }, Data: map[string]string{}, }).Build(), - newClientFunc: clientWithLoginMock, + newClientFunc: fake.ClientWithLoginMock, }, want: want{ err: fmt.Errorf(errConfigMapFmt, "cert"), @@ -419,7 +397,7 @@ MIIFkTCCA3mgAwIBAgIUBEUg3m/WqAsWHG4Q/II3IePFfuowDQYJKoZIhvcNAQELBQAwWDELMAkGA1UE "tls.crt": []byte("cert with mistak"), }, }).Build(), - newClientFunc: clientWithLoginMock, + newClientFunc: fake.ClientWithLoginMock, }, want: want{ err: fmt.Errorf(errClientTLSAuth, "tls: failed to find any PEM data in certificate input"), @@ -440,7 +418,7 @@ MIIFkTCCA3mgAwIBAgIUBEUg3m/WqAsWHG4Q/II3IePFfuowDQYJKoZIhvcNAQELBQAwWDELMAkGA1UE "tls.crt": clientCrt, }, }).Build(), - newClientFunc: clientWithLoginMock, + newClientFunc: fake.ClientWithLoginMock, }, want: want{ err: fmt.Errorf(errClientTLSAuth, "tls: failed to find any PEM data in key input"), @@ -456,11 +434,11 @@ MIIFkTCCA3mgAwIBAgIUBEUg3m/WqAsWHG4Q/II3IePFfuowDQYJKoZIhvcNAQELBQAwWDELMAkGA1UE } func vaultTest(t *testing.T, name string, tc testCase) { - conn := &connector{ - newVaultClient: tc.args.newClientFunc, + conn := &Connector{ + NewVaultClient: tc.args.newClientFunc, } if tc.args.newClientFunc == nil { - conn.newVaultClient = newVaultClient + conn.NewVaultClient = NewVaultClient } _, err := conn.newClient(context.Background(), tc.args.store, tc.args.kube, tc.args.corev1, tc.args.ns) if diff := cmp.Diff(tc.want.err, err, EquateErrors()); diff != "" { @@ -487,12 +465,18 @@ func TestGetSecret(t *testing.T) { "foo": "oke", "bar": "also ok?", }, + "list_of_values": []string{ + "first_value", + "second_value", + "third_value", + }, + "json_number": json.Number("42"), } type args struct { store *esv1beta1.VaultProvider kube kclient.Client - vLogical Logical + vLogical util.Logical ns string data esv1beta1.ExternalSecretDataRemoteRef } @@ -586,6 +570,38 @@ func TestGetSecret(t *testing.T) { val: []byte("something different"), }, }, + "ReadSecretWithSliceValue": { + reason: "Should return property as a joined slice", + args: args{ + store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV1).Spec.Provider.Vault, + data: esv1beta1.ExternalSecretDataRemoteRef{ + Property: "list_of_values", + }, + vLogical: &fake.Logical{ + ReadWithDataWithContextFn: fake.NewReadWithContextFn(secretWithNestedVal, nil), + }, + }, + want: want{ + err: nil, + val: []byte("first_value\nsecond_value\nthird_value"), + }, + }, + "ReadSecretWithJsonNumber": { + reason: "Should return parsed json.Number property", + args: args{ + store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV1).Spec.Provider.Vault, + data: esv1beta1.ExternalSecretDataRemoteRef{ + Property: "json_number", + }, + vLogical: &fake.Logical{ + ReadWithDataWithContextFn: fake.NewReadWithContextFn(secretWithNestedVal, nil), + }, + }, + want: want{ + err: nil, + val: []byte("42"), + }, + }, "NonexistentProperty": { reason: "Should return error property does not exist.", args: args{ @@ -763,7 +779,7 @@ func TestGetSecretMap(t *testing.T) { type args struct { store *esv1beta1.VaultProvider kube kclient.Client - vClient Logical + vClient util.Logical ns string data esv1beta1.ExternalSecretDataRemoteRef } @@ -1075,7 +1091,7 @@ func TestGetAllSecrets(t *testing.T) { type args struct { store *esv1beta1.VaultProvider kube kclient.Client - vLogical Logical + vLogical util.Logical ns string data esv1beta1.ExternalSecretFind } @@ -1436,8 +1452,8 @@ func TestValidateStore(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - c := &connector{ - newVaultClient: nil, + c := &Connector{ + NewVaultClient: nil, } store := &esv1beta1.SecretStore{ Spec: esv1beta1.SecretStoreSpec{ @@ -1468,7 +1484,7 @@ func TestSetSecret(t *testing.T) { type args struct { store *esv1beta1.VaultProvider - vLogical Logical + vLogical util.Logical } type want struct { diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 831a73b6b5c..49ae2b4aa50 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -15,8 +15,7 @@ limitations under the License. package utils import ( - //nolint:gosec - "crypto/md5" + "crypto/md5" //nolint:gosec "encoding/base64" "errors" "fmt" From 4f7683a2399718d768082e545d2c6a29fff762a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20G=C3=B3mez?= <1637983+sebagomez@users.noreply.github.com> Date: Mon, 13 Mar 2023 16:18:53 -0400 Subject: [PATCH 52/62] Updating docs (#2122) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sebastián Gómez --- docs/provider/aws-parameter-store.md | 12 ++++++++++++ docs/provider/hashicorp-vault.md | 16 ++++++++++++++++ docs/snippets/aws-sm-external-secret.yaml | 13 +++++++++++++ 3 files changed, 41 insertions(+) diff --git a/docs/provider/aws-parameter-store.md b/docs/provider/aws-parameter-store.md index 3cc3cbc8c34..a794589ca19 100644 --- a/docs/provider/aws-parameter-store.md +++ b/docs/provider/aws-parameter-store.md @@ -73,6 +73,18 @@ spec: key: friendslist property: friends.1.first # Roger + # metadataPolicy to fetch all the tags in JSON format + - secretKey: tags + remoteRef: + metadataPolicy: Fetch + key: database-credentials + + # metadataPolicy to fetch a specific tag (dev) from the source secret + - secretKey: developer + remoteRef: + metadataPolicy: Fetch + key: database-credentials + property: dev ``` ### Parameter Versions diff --git a/docs/provider/hashicorp-vault.md b/docs/provider/hashicorp-vault.md index 60e14d3300b..3d0ed13ef7b 100644 --- a/docs/provider/hashicorp-vault.md +++ b/docs/provider/hashicorp-vault.md @@ -72,6 +72,20 @@ spec: remoteRef: key: foo property: my-value + + # metadataPolicy to fetch all the labels in JSON format + - secretKey: tags + remoteRef: + metadataPolicy: Fetch + key: foo + + # metadataPolicy to fetch a specific label (dev) from the source secret + - secretKey: developer + remoteRef: + metadataPolicy: Fetch + key: foo + property: dev + --- # will create a secret with: kind: Secret @@ -81,6 +95,8 @@ data: foobar: czNjcjN0 ``` +Keep in mind that fetching the labels with `metadataPolicy: Fetch` only works with KV sercrets engine version v2. + #### Fetching Raw Values You can fetch all key/value pairs for a given path If you leave the `remoteRef.property` empty. This returns the json-encoded secret value for that path. diff --git a/docs/snippets/aws-sm-external-secret.yaml b/docs/snippets/aws-sm-external-secret.yaml index 4d320adf2ad..479253c7c21 100644 --- a/docs/snippets/aws-sm-external-secret.yaml +++ b/docs/snippets/aws-sm-external-secret.yaml @@ -19,3 +19,16 @@ spec: remoteRef: key: friendslist property: friends.1.first # Roger + + # metadataPolicy to fetch all the labels in JSON format + - secretKey: tags + remoteRef: + metadataPolicy: Fetch + key: database-credentials + + # metadataPolicy to fetch a specific label (dev) from the source secret + - secretKey: developer + remoteRef: + metadataPolicy: Fetch + key: database-credentials + property: dev From be0c946b10b085089fe8f817377e9faa12ba4b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristi=C3=A1n=20Le=C5=A1ko?= Date: Mon, 13 Mar 2023 21:22:00 +0100 Subject: [PATCH 53/62] docs: add HashiCorp Vault Generator documentation (#2123) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: add HashiCorp Vault Generator documentation Document the Vault dynamic secrets Generator from #2074. Signed-off-by: Kristián Leško * fix: add vault generator to nav Signed-off-by: Moritz Johner --------- Signed-off-by: Kristián Leško Signed-off-by: Moritz Johner Co-authored-by: Moritz Johner --- docs/api/generator/vault.md | 19 +++++++++++++++ docs/provider/hashicorp-vault.md | 8 ++++--- docs/snippets/generator-vault.yaml | 38 ++++++++++++++++++++++++++++++ hack/api-docs/mkdocs.yml | 5 ++-- 4 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 docs/api/generator/vault.md create mode 100644 docs/snippets/generator-vault.yaml diff --git a/docs/api/generator/vault.md b/docs/api/generator/vault.md new file mode 100644 index 00000000000..7b265e98669 --- /dev/null +++ b/docs/api/generator/vault.md @@ -0,0 +1,19 @@ +The `VaultDynamicSecret` Generator provides an interface to HashiCorp Vault's +[Secrets engines](https://developer.hashicorp.com/vault/docs/secrets). Specifically, +it enables obtaining dynamic secrets not covered by the +[HashiCorp Vault provider](../../provider/hashicorp-vault.md). + +Any Vault authentication method supported by the provider can be used here +(`provider` block of the spec). + +All secrets engines should be supported by providing matching `path`, `method` +and `parameters` values to the Generator spec (see example below). + +Exact output keys and values depend on the Vault secret engine used; nested values +are stored into the resulting Secret in JSON format. + +## Example manifest + +```yaml +{% include 'generator-vault.yaml' %} +``` diff --git a/docs/provider/hashicorp-vault.md b/docs/provider/hashicorp-vault.md index 3d0ed13ef7b..bb547f5e035 100644 --- a/docs/provider/hashicorp-vault.md +++ b/docs/provider/hashicorp-vault.md @@ -2,9 +2,11 @@ ## Hashicorp Vault -External Secrets Operator integrates with [HashiCorp Vault](https://www.vaultproject.io/) for secret -management. Vault itself implements lots of different secret engines, as of now we only support the -[KV Secrets Engine](https://www.vaultproject.io/docs/secrets/kv). +External Secrets Operator integrates with [HashiCorp Vault](https://www.vaultproject.io/) for secret management. + +The [KV Secrets Engine](https://www.vaultproject.io/docs/secrets/kv) is the only +one supported by this provider. For other secrets engines, please refer to the +[Vault Generator](../api/generator/vault.md). ### Example diff --git a/docs/snippets/generator-vault.yaml b/docs/snippets/generator-vault.yaml new file mode 100644 index 00000000000..63028659113 --- /dev/null +++ b/docs/snippets/generator-vault.yaml @@ -0,0 +1,38 @@ +{% raw %} + +--- +apiVersion: generators.external-secrets.io/v1alpha1 +kind: VaultDynamicSecret +metadata: + name: "pki-example" +spec: + path: "/pki/issue/example-dot-com" + method: "POST" + parameters: + common_name: "localhost" + ip_sans: "127.0.0.1,127.0.0.11" + provider: + server: "http://vault.default.svc.cluster.local:8200" + auth: + kubernetes: + mountPath: "kubernetes" + role: "external-secrets-operator" + serviceAccountRef: + name: "default" +--- +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: "pki-example-com" +spec: + refreshInterval: "768h" + target: + name: pki-example-com + dataFrom: + - sourceRef: + generatorRef: + apiVersion: generators.external-secrets.io/v1alpha1 + kind: VaultDynamicSecret + name: "pki-example" + +{% endraw %} diff --git a/hack/api-docs/mkdocs.yml b/hack/api-docs/mkdocs.yml index 62d76d04a45..850487c869b 100644 --- a/hack/api-docs/mkdocs.yml +++ b/hack/api-docs/mkdocs.yml @@ -24,8 +24,8 @@ plugins: - macros: include_dir: docs/snippets copyright: | - © 2022 The external-secrets Authors.
- © 2022 The Linux Foundation. All rights reserved.

+ © 2023 The external-secrets Authors.
+ © 2023 The Linux Foundation. All rights reserved.

The Linux Foundation has registered trademarks and uses trademarks.
For a list of trademarks of The Linux Foundation, please see our Trademark Usage page. extra: @@ -55,6 +55,7 @@ nav: - Azure Container Registry: api/generator/acr.md - AWS Elastic Container Registry: api/generator/ecr.md - Google Container Registry: api/generator/gcr.md + - Vault Dynamic Secret: api/generator/vault.md - Password: api/generator/password.md - Fake: api/generator/fake.md - Reference Docs: From 9f7a03b326932907899b64e75827d2633cc0546e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Mar 2023 21:22:36 +0100 Subject: [PATCH 54/62] chore(deps): bump golang from 1.20.1-alpine to 1.20.2-alpine (#2116) Bumps golang from 1.20.1-alpine to 1.20.2-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile.standalone | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.standalone b/Dockerfile.standalone index 3a32e89e98c..7067e801d9d 100644 --- a/Dockerfile.standalone +++ b/Dockerfile.standalone @@ -1,6 +1,6 @@ # This version of Dockerfile is for building without external dependencies. # Build a multi-platform image e.g. `docker buildx build --push --platform linux/arm64,linux/amd64 --tag external-secrets:dev --file Dockerfile.standalone .` -FROM golang:1.20.1-alpine AS builder +FROM golang:1.20.2-alpine AS builder ARG TARGETOS ARG TARGETARCH ENV CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} From 7edfff81e3c64c12d7a247c485472c8b30a1d73f Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Mon, 13 Mar 2023 22:17:48 +0100 Subject: [PATCH 55/62] chore: bump dependencies (#2124) * chore: bump dependencies Signed-off-by: Moritz Johner * fix: msal api breaking change Signed-off-by: Moritz Johner --------- Signed-off-by: Moritz Johner --- e2e/go.mod | 36 ++++----- e2e/go.sum | 75 ++++++++--------- go.mod | 52 ++++++------ go.sum | 103 ++++++++++++------------ pkg/provider/azure/keyvault/keyvault.go | 4 +- 5 files changed, 135 insertions(+), 135 deletions(-) diff --git a/e2e/go.mod b/e2e/go.mod index c2cf641b3b2..df584761719 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -42,27 +42,27 @@ require ( github.com/Azure/azure-sdk-for-go v68.0.0+incompatible github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 - github.com/akeylesslabs/akeyless-go/v3 v3.2.6 - github.com/aliyun/alibaba-cloud-sdk-go v1.62.217 + github.com/akeylesslabs/akeyless-go/v3 v3.2.8 + github.com/aliyun/alibaba-cloud-sdk-go v1.62.236 github.com/argoproj/argo-cd/v2 v2.4.8 - github.com/aws/aws-sdk-go v1.44.214 + github.com/aws/aws-sdk-go v1.44.220 github.com/external-secrets/external-secrets v0.0.0 github.com/fluxcd/helm-controller/api v0.22.2 github.com/fluxcd/pkg/apis/meta v0.14.2 github.com/fluxcd/source-controller/api v0.25.11 github.com/golang-jwt/jwt/v4 v4.5.0 github.com/hashicorp/vault/api v1.9.0 - github.com/onsi/ginkgo/v2 v2.9.0 - github.com/onsi/gomega v1.27.1 + github.com/onsi/ginkgo/v2 v2.9.1 + github.com/onsi/gomega v1.27.3 github.com/oracle/oci-go-sdk/v56 v56.1.0 - github.com/xanzy/go-gitlab v0.80.2 + github.com/xanzy/go-gitlab v0.81.0 golang.org/x/oauth2 v0.6.0 - google.golang.org/api v0.111.0 + google.golang.org/api v0.112.0 k8s.io/api v0.26.2 k8s.io/apiextensions-apiserver v0.26.2 k8s.io/apimachinery v0.26.2 k8s.io/client-go v1.5.2 - k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 + k8s.io/utils v0.0.0-20230313181309-38a27ef9d749 sigs.k8s.io/controller-runtime v0.14.5 software.sslmate.com/src/go-pkcs12 v0.2.0 ) @@ -98,7 +98,7 @@ require ( github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dimchansky/utfbom v1.1.1 // indirect github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/emicklei/go-restful/v3 v3.10.1 // indirect + github.com/emicklei/go-restful/v3 v3.10.2 // indirect github.com/emirpasic/gods v1.12.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect @@ -122,18 +122,18 @@ require ( github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/btree v1.0.1 // indirect github.com/google/gnostic v0.6.9 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-github/v41 v41.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 // indirect + github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect - github.com/googleapis/gax-go/v2 v2.7.0 // indirect + github.com/googleapis/gax-go/v2 v2.7.1 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -175,7 +175,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.41.0 // indirect + github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/robfig/cron v1.2.0 // indirect github.com/russross/blackfriday v1.5.2 // indirect @@ -197,19 +197,19 @@ require ( go.opencensus.io v0.24.0 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect golang.org/x/crypto v0.7.0 // indirect - golang.org/x/exp v0.0.0-20230304125523-9ff063c70017 // indirect + golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0 // indirect golang.org/x/net v0.8.0 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.6.0 // indirect golang.org/x/term v0.6.0 // indirect golang.org/x/text v0.8.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.6.0 // indirect + golang.org/x/tools v0.7.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 // indirect + google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect google.golang.org/grpc v1.53.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect + google.golang.org/protobuf v1.29.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect @@ -223,7 +223,7 @@ require ( k8s.io/component-helpers v0.24.2 // indirect k8s.io/klog/v2 v2.90.1 // indirect k8s.io/kube-aggregator v0.24.2 // indirect - k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d // indirect + k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a // indirect k8s.io/kubectl v0.24.2 // indirect k8s.io/kubernetes v1.24.2 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/e2e/go.sum b/e2e/go.sum index 81fa3497fe1..e64af6b39e8 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -115,8 +115,8 @@ github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 h1:vTckjyBhHOBiOWSC/oaEU2Oo4OH5eAlQiwKu2RMxsFg= github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4/go.mod h1:As/RomC2w/fa3y+yHRlVHPmkbP+zrKBFRow41y5dk+E= -github.com/akeylesslabs/akeyless-go/v3 v3.2.6 h1:7Z5m/oANHvRWKKWhOuTNX26OalNX20qSqxR7qVyOcLU= -github.com/akeylesslabs/akeyless-go/v3 v3.2.6/go.mod h1:XtPdOYw+rrG9bxyBzuQ5zAGCUTd364R2grs7GsZ5nos= +github.com/akeylesslabs/akeyless-go/v3 v3.2.8 h1:0/Z23ijycZRBvXnEGDMivF9HZU6vtAU+lGB5FRb638M= +github.com/akeylesslabs/akeyless-go/v3 v3.2.8/go.mod h1:XtPdOYw+rrG9bxyBzuQ5zAGCUTd364R2grs7GsZ5nos= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -125,8 +125,8 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI= github.com/alicebob/miniredis/v2 v2.14.2 h1:VeoqKUAsJfT2af61nDE7qhBzqn3J6xjnt9MFAbdrEtg= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.217 h1:YZPv3FMTEP9s5u547eY3E+7s8FothzjWvITtqwhljSE= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.217/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.236 h1:Kfwu9B93qq3fPHPqBHOXZU4lc+qf/e5XEsrlHNuizhU= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.236/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -154,8 +154,8 @@ github.com/aws/aws-sdk-go v1.33.16/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZve github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= github.com/aws/aws-sdk-go v1.38.49/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.44.214 h1:YzDuC+9UtrAOUkItlK7l3BvKI9o6qAog9X8i289HORc= -github.com/aws/aws-sdk-go v1.44.214/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.220 h1:yAj99qAt0Htjle9Up3DglgHfOP77lmFPrElA4jKnrBo= +github.com/aws/aws-sdk-go v1.44.220/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -270,8 +270,8 @@ github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7fo github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= -github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE= +github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= @@ -294,7 +294,7 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZM github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/fluxcd/helm-controller/api v0.22.2 h1:nh0GZBsUE0gNzm4PmPa4aOoqYlbZbpGt2pcIL9S2184= @@ -433,8 +433,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= @@ -484,8 +485,8 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 h1:CqYfpuYIjnlNxM3msdyPRKabhXZWbKjf3Q8BWROFBso= -github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= +github.com/google/pprof v0.0.0-20230309165930-d61513b1440d h1:um9/pc7tKMINFfP1eE7Wv6PRGXlcCSJkVajF7KJw3uQ= +github.com/google/pprof v0.0.0-20230309165930-d61513b1440d/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -498,8 +499,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9 github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.7.1 h1:gF4c0zjUP2H/s/hEGyLA3I0fA2ZWjzYiONAD6cvPr8A= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -742,15 +743,15 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.9.0 h1:Tugw2BKlNHTMfG+CheOITkYvk4LAh6MFOvikhGVnhE8= -github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk= +github.com/onsi/ginkgo/v2 v2.9.1 h1:zie5Ly042PD3bsCvsSOPvRnFwyo3rKe64TJlD6nu0mk= +github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= -github.com/onsi/gomega v1.27.1 h1:rfztXRbg6nv/5f+Raen9RcGoSecHIFgBBLQK3Wdj754= -github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfadcIAw= +github.com/onsi/gomega v1.27.3 h1:5VwIwnBY3vbBDOJrNtA4rVdiTZCsq9B5F12pvy1Drmk= +github.com/onsi/gomega v1.27.3/go.mod h1:5vG284IBtfDAmDyrK+eGyZmUgUlmi+Wngqo557cZ6Gw= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -821,8 +822,8 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.41.0 h1:npo01n6vUlRViIj5fgwiK8vlNIh8bnoxqh3gypKsyAw= -github.com/prometheus/common v0.41.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -956,8 +957,8 @@ github.com/vmihailenco/msgpack/v5 v5.3.4/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= -github.com/xanzy/go-gitlab v0.80.2 h1:CH1Q7NDklqZllox4ICVF4PwlhQGfPtE+w08Jsb74ZX0= -github.com/xanzy/go-gitlab v0.80.2/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M= +github.com/xanzy/go-gitlab v0.81.0 h1:ofbhZ5ZY9AjHATWQie4qd2JfncdUmvcSA/zfQB767Dk= +github.com/xanzy/go-gitlab v0.81.0/go.mod h1:VMbY3JIWdZ/ckvHbQqkyd3iYk2aViKrNIQ23IbFMQDo= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -1027,7 +1028,7 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/ go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= @@ -1075,8 +1076,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20210220032938-85be41e4509f/go.mod h1:I6l2HNBLBZEcrOoCpyKLdY2lHoRZ8lI4x60KMCQDft4= golang.org/x/exp v0.0.0-20210901193431-a062eea981d2/go.mod h1:a3o/VtDNHN+dCVLEpzjjUHOzR+Ln3DHX056ZPzoZGGA= -golang.org/x/exp v0.0.0-20230304125523-9ff063c70017 h1:3Ea9SZLCB0aRIhSEjM+iaGIlzzeDJdpi579El/YIhEE= -golang.org/x/exp v0.0.0-20230304125523-9ff063c70017/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0 h1:LGJsf5LRplCck6jUCH3dBL2dmycNruWNF5xugkSlfXw= +golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1387,8 +1388,8 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1426,8 +1427,8 @@ google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.45.0/go.mod h1:ISLIJCedJolbZvDfAk+Ctuq5hf+aJ33WgtUsfyFoLXA= google.golang.org/api v0.46.0/go.mod h1:ceL4oozhkAiTID8XMmJBsIxID/9wMXJVVFXPg4ylg3I= -google.golang.org/api v0.111.0 h1:bwKi+z2BsdwYFRKrqwutM+axAlYLz83gt5pDSXCJT+0= -google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= +google.golang.org/api v0.112.0 h1:iDmzvZ4C086R3+en4nSyIf07HlQKMOX1Xx2dmia/+KQ= +google.golang.org/api v0.112.0/go.mod h1:737UfWHNsOq4F3REUTmb+GN9pugkgNLCayLTfoIKpPc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1487,8 +1488,8 @@ google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 h1:QQF+HdiI4iocoxUjjpLgvTYDHKm99C/VtTBFnfiCJos= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1531,8 +1532,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.0 h1:44S3JjaKmLEE4YIkjzexaP+NzZsudE3Zin5Njn/pYX0= +google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1630,8 +1631,8 @@ k8s.io/kube-aggregator v0.24.2/go.mod h1:Ju2jNDixn+vqeeKEBfjfpc204bO1pbdXX0N9knC k8s.io/kube-controller-manager v0.24.2/go.mod h1:KDE0yqiEvxYiO0WRpPA4rVx8AcK1vsWydUF37AJ9lTI= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d h1:VcFq5n7wCJB2FQMCIHfC+f+jNcGgNMar1uKd6rVlifU= -k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY= +k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a h1:gmovKNur38vgoWfGtP5QOGNOA7ki4n6qNYoFAgMlNvg= +k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY= k8s.io/kube-proxy v0.24.2/go.mod h1:bozS2ufl/Ns6s40Ue34eV7rqyLVygi5usSmCgW7rFU8= k8s.io/kube-scheduler v0.24.2/go.mod h1:DRa+aeXKSYUUOHHIc/9EcaO9+FW5FydaOfPSvaSW5Ko= k8s.io/kubectl v0.24.2 h1:+RfQVhth8akUmIc2Ge8krMl/pt66V7210ka3RE/p0J4= @@ -1648,8 +1649,8 @@ k8s.io/system-validators v1.7.0/go.mod h1:gP1Ky+R9wtrSiFbrpEPwWMeYz9yqyy1S/KOh0V k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk= -k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20230313181309-38a27ef9d749 h1:xMMXJlJbsU8w3V5N2FLDQ8YgU8s1EoULdbQBcAeNJkY= +k8s.io/utils v0.0.0-20230313181309-38a27ef9d749/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= diff --git a/go.mod b/go.mod index 27071ebd7a3..eaf8fc91771 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/Azure/go-autorest/autorest v0.11.28 github.com/Azure/go-autorest/autorest/adal v0.9.22 github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 - github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 + github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 github.com/IBM/go-sdk-core/v5 v5.13.1 github.com/IBM/secrets-manager-go-sdk v1.0.49 github.com/Masterminds/goutils v1.1.1 // indirect @@ -17,36 +17,36 @@ require ( github.com/PaesslerAG/jsonpath v0.1.1 github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 - github.com/aliyun/alibaba-cloud-sdk-go v1.62.217 - github.com/aws/aws-sdk-go v1.44.214 + github.com/aliyun/alibaba-cloud-sdk-go v1.62.236 + github.com/aws/aws-sdk-go v1.44.220 github.com/go-logr/logr v1.2.3 github.com/go-test/deep v1.0.4 // indirect github.com/google/go-cmp v0.5.9 github.com/google/uuid v1.3.0 - github.com/googleapis/gax-go/v2 v2.7.0 + github.com/googleapis/gax-go/v2 v2.7.1 github.com/hashicorp/vault/api v1.9.0 github.com/hashicorp/vault/api/auth/approle v0.4.0 github.com/hashicorp/vault/api/auth/kubernetes v0.4.0 github.com/hashicorp/vault/api/auth/ldap v0.4.0 github.com/huandu/xstrings v1.4.0 // indirect github.com/lestrrat-go/jwx v1.2.25 - github.com/onsi/ginkgo/v2 v2.9.0 - github.com/onsi/gomega v1.27.1 + github.com/onsi/ginkgo/v2 v2.9.1 + github.com/onsi/gomega v1.27.3 github.com/oracle/oci-go-sdk/v56 v56.1.0 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 github.com/spf13/cobra v1.6.1 github.com/stretchr/testify v1.8.2 github.com/tidwall/gjson v1.14.4 - github.com/xanzy/go-gitlab v0.80.2 - github.com/yandex-cloud/go-genproto v0.0.0-20230227093831-780473185775 - github.com/yandex-cloud/go-sdk v0.0.0-20230227095001-b676d5d7bc73 + github.com/xanzy/go-gitlab v0.81.0 + github.com/yandex-cloud/go-genproto v0.0.0-20230313091643-1b34b32615e2 + github.com/yandex-cloud/go-sdk v0.0.0-20230313092059-6ef6567e9d36 github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a go.uber.org/zap v1.24.0 golang.org/x/crypto v0.7.0 golang.org/x/oauth2 v0.6.0 - google.golang.org/api v0.111.0 - google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 // indirect + google.golang.org/api v0.112.0 + google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect google.golang.org/grpc v1.53.0 gopkg.in/yaml.v3 v3.0.1 grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 @@ -54,7 +54,7 @@ require ( k8s.io/apiextensions-apiserver v0.26.2 k8s.io/apimachinery v0.26.2 k8s.io/client-go v0.26.2 - k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 + k8s.io/utils v0.0.0-20230313181309-38a27ef9d749 sigs.k8s.io/controller-runtime v0.14.5 sigs.k8s.io/controller-tools v0.11.3 ) @@ -63,8 +63,8 @@ require github.com/1Password/connect-sdk-go v1.5.0 require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 - github.com/akeylesslabs/akeyless-go/v3 v3.2.6 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 + github.com/akeylesslabs/akeyless-go/v3 v3.2.8 github.com/hashicorp/golang-lru v0.5.4 github.com/keeper-security/secrets-manager-go/core v1.5.0 github.com/maxbrunsfeld/counterfeiter/v6 v6.6.1 @@ -98,10 +98,10 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect github.com/dimchansky/utfbom v1.1.1 // indirect - github.com/emicklei/go-restful/v3 v3.10.1 // indirect + github.com/emicklei/go-restful/v3 v3.10.2 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect - github.com/fatih/color v1.14.1 // indirect + github.com/fatih/color v1.15.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-logr/zapr v1.2.3 // indirect @@ -114,15 +114,15 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/gobuffalo/flect v1.0.2 // indirect - github.com/goccy/go-json v0.10.0 // indirect + github.com/goccy/go-json v0.10.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic v0.6.9 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 // indirect + github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -163,7 +163,7 @@ require ( github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/common v0.41.0 // indirect + github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect @@ -177,27 +177,27 @@ require ( go.mongodb.org/mongo-driver v1.11.2 // indirect go.opencensus.io v0.24.0 // indirect go.uber.org/atomic v1.10.0 // indirect - go.uber.org/multierr v1.9.0 // indirect - golang.org/x/exp v0.0.0-20230304125523-9ff063c70017 + go.uber.org/multierr v1.10.0 // indirect + golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0 golang.org/x/mod v0.9.0 // indirect golang.org/x/net v0.8.0 // indirect golang.org/x/sys v0.6.0 // indirect golang.org/x/term v0.6.0 // indirect golang.org/x/text v0.8.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.6.0 // indirect + golang.org/x/tools v0.7.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.28.1 // indirect + google.golang.org/protobuf v1.29.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect k8s.io/component-base v0.26.2 // indirect - k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9 // indirect + k8s.io/gengo v0.0.0-20230306165830-ab3349d207d4 // indirect k8s.io/klog v1.0.0 // indirect k8s.io/klog/v2 v2.90.1 // indirect - k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d // indirect + k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/go.sum b/go.sum index ccb752bbd10..a2b35b343ef 100644 --- a/go.sum +++ b/go.sum @@ -52,8 +52,8 @@ github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 h1:rTnT/Jrcm+figWlYz4Ixzt0SJVR2cMC8lvZcimipiEY= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 h1:uqM+VoHjVH6zdlkLF2b6O0ZANcHoj3rO0PoQ3jglUJA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2/go.mod h1:twTKAa1E6hLmSDjLhaCkbTMQKc7p/rNLU40rLxGEOCI= github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw= github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= @@ -82,8 +82,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg= -github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0= +github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 h1:UE9n9rkJF62ArLb1F3DEjRt8O3jLwMWdSoypKV4f3MU= +github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= @@ -110,18 +110,18 @@ github.com/ahmetb/gen-crd-api-reference-docs v0.3.0/go.mod h1:TdjdkYhlOifCQWPs1U github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4 h1:vTckjyBhHOBiOWSC/oaEU2Oo4OH5eAlQiwKu2RMxsFg= github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4/go.mod h1:As/RomC2w/fa3y+yHRlVHPmkbP+zrKBFRow41y5dk+E= -github.com/akeylesslabs/akeyless-go/v3 v3.2.6 h1:7Z5m/oANHvRWKKWhOuTNX26OalNX20qSqxR7qVyOcLU= -github.com/akeylesslabs/akeyless-go/v3 v3.2.6/go.mod h1:XtPdOYw+rrG9bxyBzuQ5zAGCUTd364R2grs7GsZ5nos= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.217 h1:YZPv3FMTEP9s5u547eY3E+7s8FothzjWvITtqwhljSE= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.217/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= +github.com/akeylesslabs/akeyless-go/v3 v3.2.8 h1:0/Z23ijycZRBvXnEGDMivF9HZU6vtAU+lGB5FRb638M= +github.com/akeylesslabs/akeyless-go/v3 v3.2.8/go.mod h1:XtPdOYw+rrG9bxyBzuQ5zAGCUTd364R2grs7GsZ5nos= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.236 h1:Kfwu9B93qq3fPHPqBHOXZU4lc+qf/e5XEsrlHNuizhU= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.236/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.44.214 h1:YzDuC+9UtrAOUkItlK7l3BvKI9o6qAog9X8i289HORc= -github.com/aws/aws-sdk-go v1.44.214/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.220 h1:yAj99qAt0Htjle9Up3DglgHfOP77lmFPrElA4jKnrBo= +github.com/aws/aws-sdk-go v1.44.220/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -159,8 +159,8 @@ github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= -github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE= +github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -177,8 +177,8 @@ github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJ github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= @@ -223,8 +223,8 @@ github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3a github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA= github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= -github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.10.1 h1:lEs5Ob+oOG/Ze199njvzHbhn6p9T+h64F5hRj69iTTo= +github.com/goccy/go-json v0.10.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= @@ -264,8 +264,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -305,8 +306,8 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 h1:CqYfpuYIjnlNxM3msdyPRKabhXZWbKjf3Q8BWROFBso= -github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= +github.com/google/pprof v0.0.0-20230309165930-d61513b1440d h1:um9/pc7tKMINFfP1eE7Wv6PRGXlcCSJkVajF7KJw3uQ= +github.com/google/pprof v0.0.0-20230309165930-d61513b1440d/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -316,8 +317,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9 github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.7.1 h1:gF4c0zjUP2H/s/hEGyLA3I0fA2ZWjzYiONAD6cvPr8A= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= @@ -469,10 +470,10 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.9.0 h1:Tugw2BKlNHTMfG+CheOITkYvk4LAh6MFOvikhGVnhE8= -github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk= -github.com/onsi/gomega v1.27.1 h1:rfztXRbg6nv/5f+Raen9RcGoSecHIFgBBLQK3Wdj754= -github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfadcIAw= +github.com/onsi/ginkgo/v2 v2.9.1 h1:zie5Ly042PD3bsCvsSOPvRnFwyo3rKe64TJlD6nu0mk= +github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= +github.com/onsi/gomega v1.27.3 h1:5VwIwnBY3vbBDOJrNtA4rVdiTZCsq9B5F12pvy1Drmk= +github.com/onsi/gomega v1.27.3/go.mod h1:5vG284IBtfDAmDyrK+eGyZmUgUlmi+Wngqo557cZ6Gw= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= @@ -491,8 +492,8 @@ github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQg github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.41.0 h1:npo01n6vUlRViIj5fgwiK8vlNIh8bnoxqh3gypKsyAw= -github.com/prometheus/common v0.41.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -553,18 +554,18 @@ github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaO github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/xanzy/go-gitlab v0.80.2 h1:CH1Q7NDklqZllox4ICVF4PwlhQGfPtE+w08Jsb74ZX0= -github.com/xanzy/go-gitlab v0.80.2/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M= +github.com/xanzy/go-gitlab v0.81.0 h1:ofbhZ5ZY9AjHATWQie4qd2JfncdUmvcSA/zfQB767Dk= +github.com/xanzy/go-gitlab v0.81.0/go.mod h1:VMbY3JIWdZ/ckvHbQqkyd3iYk2aViKrNIQ23IbFMQDo= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/yandex-cloud/go-genproto v0.0.0-20230227093831-780473185775 h1:UdzHYFFZjQ2CqozbzHiddhvCNc9J8GN83jQqsC7K3VM= -github.com/yandex-cloud/go-genproto v0.0.0-20230227093831-780473185775/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= -github.com/yandex-cloud/go-sdk v0.0.0-20230227095001-b676d5d7bc73 h1:z0JIWqWBOt1Ue4tvgIrKa22KMY+IVtaM/bM2vGJrIA8= -github.com/yandex-cloud/go-sdk v0.0.0-20230227095001-b676d5d7bc73/go.mod h1:JtxzmSeRZaGwxGICpHE2U7Fl+EFHWKobm4HkeVUA2e0= +github.com/yandex-cloud/go-genproto v0.0.0-20230313091643-1b34b32615e2 h1:lj7j36CQGHcR2MwnXdSY8NX9YSb2ZDpGtB4s3dYy7MM= +github.com/yandex-cloud/go-genproto v0.0.0-20230313091643-1b34b32615e2/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= +github.com/yandex-cloud/go-sdk v0.0.0-20230313092059-6ef6567e9d36 h1:IXf80ZAhm00D8CRe8m/YF9DglQpw47mJJl+UKcPZ6O8= +github.com/yandex-cloud/go-sdk v0.0.0-20230313092059-6ef6567e9d36/go.mod h1:v5pygm/XH7Q5FPbeOoYvfrbvWNcBFJs6ziA2d10ZTbY= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= @@ -593,8 +594,8 @@ go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0 go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= @@ -626,8 +627,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230304125523-9ff063c70017 h1:3Ea9SZLCB0aRIhSEjM+iaGIlzzeDJdpi579El/YIhEE= -golang.org/x/exp v0.0.0-20230304125523-9ff063c70017/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0 h1:LGJsf5LRplCck6jUCH3dBL2dmycNruWNF5xugkSlfXw= +golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -861,8 +862,8 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -895,8 +896,8 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.45.0/go.mod h1:ISLIJCedJolbZvDfAk+Ctuq5hf+aJ33WgtUsfyFoLXA= -google.golang.org/api v0.111.0 h1:bwKi+z2BsdwYFRKrqwutM+axAlYLz83gt5pDSXCJT+0= -google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= +google.golang.org/api v0.112.0 h1:iDmzvZ4C086R3+en4nSyIf07HlQKMOX1Xx2dmia/+KQ= +google.golang.org/api v0.112.0/go.mod h1:737UfWHNsOq4F3REUTmb+GN9pugkgNLCayLTfoIKpPc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -948,8 +949,8 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 h1:QQF+HdiI4iocoxUjjpLgvTYDHKm99C/VtTBFnfiCJos= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -987,8 +988,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.0 h1:44S3JjaKmLEE4YIkjzexaP+NzZsudE3Zin5Njn/pYX0= +google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1038,18 +1039,18 @@ k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU= k8s.io/component-base v0.26.2 h1:IfWgCGUDzrD6wLLgXEstJKYZKAFS2kO+rBRi0p3LqcI= k8s.io/component-base v0.26.2/go.mod h1:DxbuIe9M3IZPRxPIzhch2m1eT7uFrSBJUBuVCQEBivs= k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9 h1:iu3o/SxaHVI7tKPtkGzD3M9IzrE21j+CUKH98NQJ8Ms= -k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20230306165830-ab3349d207d4 h1:aClvVG6GbX10ISHcc24J+tqbr0S7fEe1MWkFJ7cWWCI= +k8s.io/gengo v0.0.0-20230306165830-ab3349d207d4/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d h1:VcFq5n7wCJB2FQMCIHfC+f+jNcGgNMar1uKd6rVlifU= -k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY= -k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk= -k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a h1:gmovKNur38vgoWfGtP5QOGNOA7ki4n6qNYoFAgMlNvg= +k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY= +k8s.io/utils v0.0.0-20230313181309-38a27ef9d749 h1:xMMXJlJbsU8w3V5N2FLDQ8YgU8s1EoULdbQBcAeNJkY= +k8s.io/utils v0.0.0-20230313181309-38a27ef9d749/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= diff --git a/pkg/provider/azure/keyvault/keyvault.go b/pkg/provider/azure/keyvault/keyvault.go index 44c2582182f..bd20f79d4c3 100644 --- a/pkg/provider/azure/keyvault/keyvault.go +++ b/pkg/provider/azure/keyvault/keyvault.go @@ -834,9 +834,7 @@ func NewTokenProvider(ctx context.Context, token, clientID, tenantID, aadEndpoin cred := confidential.NewCredFromAssertionCallback(func(ctx context.Context, aro confidential.AssertionRequestOptions) (string, error) { return token, nil }) - cClient, err := confidential.New(clientID, cred, confidential.WithAuthority( - fmt.Sprintf("%s%s/oauth2/token", aadEndpoint, tenantID), - )) + cClient, err := confidential.New(fmt.Sprintf("%s%s/oauth2/token", aadEndpoint, tenantID), clientID, cred) if err != nil { return nil, err } From 05dacdc104553f18e492a75902309c776d7883af Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Mon, 13 Mar 2023 22:31:29 +0100 Subject: [PATCH 56/62] chore: update docs for release (#2126) Signed-off-by: Moritz Johner --- docs/contributing/roadmap.md | 25 ++++++----- docs/introduction/stability-support.md | 59 +++++++++++++------------ hack/api-docs/mkdocs.yml | 1 + pkg/provider/azure/keyvault/keyvault.go | 2 +- 4 files changed, 46 insertions(+), 41 deletions(-) diff --git a/docs/contributing/roadmap.md b/docs/contributing/roadmap.md index ecb54f900ed..7eccd318acf 100644 --- a/docs/contributing/roadmap.md +++ b/docs/contributing/roadmap.md @@ -11,21 +11,24 @@ These CRDs are currently at `v1beta1` and are considered production ready. Going We have identified the following areas of work. This is subject to change while we gather feedback. We have a [GitHub Project Board](https://github.com/orgs/external-secrets/projects/2/views/1) where we organize issues and milestones on a high level. + * Conformance testing - * end to end testing with ArgoCD and Flux - * end to end testing for all project maintained providers + * ✓ end to end testing with ArgoCD and Flux + * ✓ end to end testing for all project maintained providers * API enhancements * consolidate provider fields - * dataFrom key rewrites + * ✓ dataFrom key rewrites * provider versioning strategy - * pushing secrets to a provider + * ✓ pushing secrets to a provider * Documentation Improvements * Troubleshooting Guides - * FAQ - * review multi tenancy docs - * provide security model for infosec teams - * provider specific guides + * ✓ FAQ + * ✓ review multi tenancy docs + * security model for infosec teams + * security best practices guide + * ✓ provider specific guides * Observability - * Provide Grafana Dashboard and Prometheus alerts - * add provider-level metrics -* Pentest & SBOM + * ✓ Provide Grafana Dashboard and Prometheus alerts + * ✓ add provider-level metrics +* Pentest +* ✓ SBOM diff --git a/docs/introduction/stability-support.md b/docs/introduction/stability-support.md index 0706ddf44f4..8aa2fca437f 100644 --- a/docs/introduction/stability-support.md +++ b/docs/introduction/stability-support.md @@ -11,6 +11,7 @@ We are currently in beta and support **only the latest release** for the time be | ESO Version | Kubernetes Version | | ----------- | ------------------ | +| 0.8.x | 1.19 → 1.26 | | 0.7.x | 1.19 → 1.26 | | 0.6.x | 1.19 → 1.24 | | 0.5.x | 1.19 → 1.24 | @@ -21,37 +22,37 @@ We are currently in beta and support **only the latest release** for the time be The following table describes the stability level of each provider and who's responsible. -| Provider | Stability | Maintainer | -|------------------------------------------------------------------------------------------------------------|:---------:|-----------------------------------------------------------------------------------------------------------------------------------------------:| -| [AWS Secrets Manager](https://external-secrets.io/latest/provider/aws-secrets-manager/) | stable | [external-secrets](https://github.com/external-secrets) | -| [AWS Parameter Store](https://external-secrets.io/latest/provider/aws-parameter-store/) | stable | [external-secrets](https://github.com/external-secrets) | -| [Hashicorp Vault](https://external-secrets.io/latest/provider/hashicorp-vault/) | stable | [external-secrets](https://github.com/external-secrets) | -| [GCP Secret Manager](https://external-secrets.io/latest/provider/google-secrets-manager/) | stable | [external-secrets](https://github.com/external-secrets) | -| [Azure Keyvault](https://external-secrets.io/latest/provider/azure-key-vault/) | stable | [external-secrets](https://github.com/external-secrets) | +| Provider | Stability | Maintainer | +| ---------------------------------------------------------------------------------------------------------- | :-------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | +| [AWS Secrets Manager](https://external-secrets.io/latest/provider/aws-secrets-manager/) | stable | [external-secrets](https://github.com/external-secrets) | +| [AWS Parameter Store](https://external-secrets.io/latest/provider/aws-parameter-store/) | stable | [external-secrets](https://github.com/external-secrets) | +| [Hashicorp Vault](https://external-secrets.io/latest/provider/hashicorp-vault/) | stable | [external-secrets](https://github.com/external-secrets) | +| [GCP Secret Manager](https://external-secrets.io/latest/provider/google-secrets-manager/) | stable | [external-secrets](https://github.com/external-secrets) | +| [Azure Keyvault](https://external-secrets.io/latest/provider/azure-key-vault/) | stable | [external-secrets](https://github.com/external-secrets) | | [IBM Cloud Secrets Manager](https://external-secrets.io/latest/provider/ibm-secrets-manager/) | stable | [@knelasevero](https://github.com/knelasevero) [@sebagomez](https://github.com/sebagomez) [@ricardoptcosta](https://github.com/ricardoptcosta) [@IdanAdar](https://github.com/IdanAdar) | -| [Kubernetes](https://external-secrets.io/latest/provider/kubernetes) | alpha | [external-secrets](https://github.com/external-secrets) | -| [Yandex Lockbox](https://external-secrets.io/latest/provider/yandex-lockbox/) | alpha | [@AndreyZamyslov](https://github.com/AndreyZamyslov) [@knelasevero](https://github.com/knelasevero) | -| [Gitlab Variables](https://external-secrets.io/latest/provider/gitlab-variables/) | alpha | [@Jabray5](https://github.com/Jabray5) | -| Alibaba Cloud KMS | alpha | [@ElsaChelala](https://github.com/ElsaChelala) | -| [Oracle Vault](https://external-secrets.io/latest/provider/oracle-vault) | alpha | [@KianTigger](https://github.com/KianTigger) [@EladGabay](https://github.com/EladGabay) | -| [Akeyless](https://external-secrets.io/latest/provider/akeyless) | alpha | [@renanaAkeyless](https://github.com/renanaAkeyless) | -| [1Password](https://external-secrets.io/latest/provider/1password-automation) | alpha | [@SimSpaceCorp](https://github.com/Simspace) [@snarlysodboxer](https://github.com/snarlysodboxer) | -| [Generic Webhook](https://external-secrets.io/latest/provider/webhook) | alpha | [@willemm](https://github.com/willemm) | -| [senhasegura DevOps Secrets Management (DSM)](https://external-secrets.io/latest/provider/senhasegura-dsm) | alpha | [@lfraga](https://github.com/lfraga) | -| [Doppler SecretOps Platform](https://external-secrets.io/latest/provider/doppler) | alpha | [@ryan-blunden](https://github.com/ryan-blunden/) [@nmanoogian](https://github.com/nmanoogian/) | +| [Kubernetes](https://external-secrets.io/latest/provider/kubernetes) | alpha | [external-secrets](https://github.com/external-secrets) | +| [Yandex Lockbox](https://external-secrets.io/latest/provider/yandex-lockbox/) | alpha | [@AndreyZamyslov](https://github.com/AndreyZamyslov) [@knelasevero](https://github.com/knelasevero) | +| [Gitlab Variables](https://external-secrets.io/latest/provider/gitlab-variables/) | alpha | [@Jabray5](https://github.com/Jabray5) | +| Alibaba Cloud KMS | alpha | [@ElsaChelala](https://github.com/ElsaChelala) | +| [Oracle Vault](https://external-secrets.io/latest/provider/oracle-vault) | alpha | [@KianTigger](https://github.com/KianTigger) [@EladGabay](https://github.com/EladGabay) | +| [Akeyless](https://external-secrets.io/latest/provider/akeyless) | alpha | [@renanaAkeyless](https://github.com/renanaAkeyless) | +| [1Password](https://external-secrets.io/latest/provider/1password-automation) | alpha | [@SimSpaceCorp](https://github.com/Simspace) [@snarlysodboxer](https://github.com/snarlysodboxer) | +| [Generic Webhook](https://external-secrets.io/latest/provider/webhook) | alpha | [@willemm](https://github.com/willemm) | +| [senhasegura DevOps Secrets Management (DSM)](https://external-secrets.io/latest/provider/senhasegura-dsm) | alpha | [@lfraga](https://github.com/lfraga) | +| [Doppler SecretOps Platform](https://external-secrets.io/latest/provider/doppler) | alpha | [@ryan-blunden](https://github.com/ryan-blunden/) [@nmanoogian](https://github.com/nmanoogian/) | ## Provider Feature Support The following table show the support for features across different providers. | Provider | find by name | find by tags | metadataPolicy Fetch | referent authentication | store validation | push secret | DeletionPolicy Merge/Delete | -|---------------------------|:------------:|:------------:| :------------------: | :---------------------: | :--------------: | :---------: | :-------------------------: -| AWS Secrets Manager | x | x | | x | x | x | x | -| AWS Parameter Store | x | x | | x | x | x | x | -| Hashicorp Vault | x | x | | x | x | x | x | -| GCP Secret Manager | x | x | | x | x | x | x | -| Azure Keyvault | x | x | x | x | x | x | x | -| Kubernetes | x | x | | x | x | x | x | +| ------------------------- | :----------: | :----------: | :------------------: | :---------------------: | :--------------: | :---------: | :-------------------------: | +| AWS Secrets Manager | x | x | x | x | x | x | x | +| AWS Parameter Store | x | x | x | x | x | x | x | +| Hashicorp Vault | x | x | x | x | x | x | x | +| GCP Secret Manager | x | x | | x | x | x | x | +| Azure Keyvault | x | x | x | x | x | x | x | +| Kubernetes | x | x | | x | x | | x | | IBM Cloud Secrets Manager | | | | | x | | | | Yandex Lockbox | | | | | x | | | | Gitlab Variables | x | x | | | x | | | @@ -59,21 +60,21 @@ The following table show the support for features across different providers. | Oracle Vault | | | | | x | | | | Akeyless | x | x | | | x | | | | 1Password | x | | | | x | | | -| Generic Webhook | | | | | | | x | +| Generic Webhook | | | | | | | x | | senhasegura DSM | | | | | x | | | | Doppler | x | | | | x | | | - ## Support Policy We provide technical support and security / bug fixes for the above listed versions. ### Technical support + We provide assistance for deploying/upgrading etc. on a best-effort basis. You can request support through the following channels: -* [Kubernetes Slack +- [Kubernetes Slack #external-secrets](https://kubernetes.slack.com/messages/external-secrets) -* GitHub [Issues](https://github.com/external-secrets/external-secrets/issues) -* GitHub [Discussions](https://github.com/external-secrets/external-secrets/discussions) +- GitHub [Issues](https://github.com/external-secrets/external-secrets/issues) +- GitHub [Discussions](https://github.com/external-secrets/external-secrets/discussions) Even though we have active maintainers and people assigned to this project, we kindly ask for patience when asking for support. We will try to get to priority issues as fast as possible, but there may be some delays. diff --git a/hack/api-docs/mkdocs.yml b/hack/api-docs/mkdocs.yml index 850487c869b..5a0d0c01e84 100644 --- a/hack/api-docs/mkdocs.yml +++ b/hack/api-docs/mkdocs.yml @@ -78,6 +78,7 @@ nav: - Rewriting Keys: guides/datafrom-rewrite.md - Upgrading to v1beta1: guides/v1beta1.md - Using Latest Image: guides/using-latest-image.md + - Disable Cluster Features: guides/disable-cluster-features.md - Provider: - AWS Secrets Manager: provider/aws-secrets-manager.md - AWS Parameter Store: provider/aws-parameter-store.md diff --git a/pkg/provider/azure/keyvault/keyvault.go b/pkg/provider/azure/keyvault/keyvault.go index bd20f79d4c3..7d4c76dbb01 100644 --- a/pkg/provider/azure/keyvault/keyvault.go +++ b/pkg/provider/azure/keyvault/keyvault.go @@ -124,7 +124,7 @@ func init() { // Capabilities return the provider supported capabilities (ReadOnly, WriteOnly, ReadWrite). func (a *Azure) Capabilities() esv1beta1.SecretStoreCapabilities { - return esv1beta1.SecretStoreReadOnly + return esv1beta1.SecretStoreReadWrite } // NewClient constructs a new secrets client based on the provided store. From 7980d5555773d06b06402266730103af2447addf Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Mon, 13 Mar 2023 23:05:37 +0100 Subject: [PATCH 57/62] feat: add keeper security, promote kubernetes provider to beta (#2127) Signed-off-by: Moritz Johner --- docs/introduction/stability-support.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/introduction/stability-support.md b/docs/introduction/stability-support.md index 8aa2fca437f..f99c2f914be 100644 --- a/docs/introduction/stability-support.md +++ b/docs/introduction/stability-support.md @@ -30,7 +30,7 @@ The following table describes the stability level of each provider and who's res | [GCP Secret Manager](https://external-secrets.io/latest/provider/google-secrets-manager/) | stable | [external-secrets](https://github.com/external-secrets) | | [Azure Keyvault](https://external-secrets.io/latest/provider/azure-key-vault/) | stable | [external-secrets](https://github.com/external-secrets) | | [IBM Cloud Secrets Manager](https://external-secrets.io/latest/provider/ibm-secrets-manager/) | stable | [@knelasevero](https://github.com/knelasevero) [@sebagomez](https://github.com/sebagomez) [@ricardoptcosta](https://github.com/ricardoptcosta) [@IdanAdar](https://github.com/IdanAdar) | -| [Kubernetes](https://external-secrets.io/latest/provider/kubernetes) | alpha | [external-secrets](https://github.com/external-secrets) | +| [Kubernetes](https://external-secrets.io/latest/provider/kubernetes) | beta | [external-secrets](https://github.com/external-secrets) | | [Yandex Lockbox](https://external-secrets.io/latest/provider/yandex-lockbox/) | alpha | [@AndreyZamyslov](https://github.com/AndreyZamyslov) [@knelasevero](https://github.com/knelasevero) | | [Gitlab Variables](https://external-secrets.io/latest/provider/gitlab-variables/) | alpha | [@Jabray5](https://github.com/Jabray5) | | Alibaba Cloud KMS | alpha | [@ElsaChelala](https://github.com/ElsaChelala) | @@ -40,6 +40,7 @@ The following table describes the stability level of each provider and who's res | [Generic Webhook](https://external-secrets.io/latest/provider/webhook) | alpha | [@willemm](https://github.com/willemm) | | [senhasegura DevOps Secrets Management (DSM)](https://external-secrets.io/latest/provider/senhasegura-dsm) | alpha | [@lfraga](https://github.com/lfraga) | | [Doppler SecretOps Platform](https://external-secrets.io/latest/provider/doppler) | alpha | [@ryan-blunden](https://github.com/ryan-blunden/) [@nmanoogian](https://github.com/nmanoogian/) | +| [Keeper Security](https://www.keepersecurity.com/) | alpha | [@ppodevlab](https://github.com/ppodevlab) | ## Provider Feature Support @@ -63,6 +64,7 @@ The following table show the support for features across different providers. | Generic Webhook | | | | | | | x | | senhasegura DSM | | | | | x | | | | Doppler | x | | | | x | | | +| Keeper Security | x | | | | x | x | | ## Support Policy From f181500e98a39dcdb90b71468b99d8d589cbf4ec Mon Sep 17 00:00:00 2001 From: azert9 Date: Thu, 16 Mar 2023 01:03:52 +0100 Subject: [PATCH 58/62] Feature/scaleway provider (#2086) * wip: basic structure of scaleway provider Signed-off-by: Julien Loctaux * test: add some tests for GetAllSecrets Signed-off-by: Julien Loctaux * feat: implement PushSecret Signed-off-by: Julien Loctaux * test: improved test fixtures Signed-off-by: Julien Loctaux * feat: allow finding secrets by project using the path property Signed-off-by: Julien Loctaux * feat: add delete secret method Signed-off-by: Julien Loctaux * Delete dupplicate of push remote ref test implem Signed-off-by: Julien Loctaux * feat: add capability to use a secret for configuring access token Signed-off-by: Julien Loctaux * feat: implement GetSecretMap Signed-off-by: Julien Loctaux * feat: filtering by name and projetc id Signed-off-by: Julien Loctaux * test: add test for finding secret by name regexp Signed-off-by: Julien Loctaux * feat: config validation Signed-off-by: Julien Loctaux * fix: handle situation where no namespace is specified and we cannot provide a default Signed-off-by: Julien Loctaux * feat: reference secrets by id or name Signed-off-by: Julien Loctaux * fix: invalid request caused by pagination handling Signed-off-by: Julien Loctaux * feat: log the error when failing to access secret version Signed-off-by: Julien Loctaux * fix: pass context to sdk where missing Signed-off-by: Julien Loctaux * feat: add a cache for reducing AccessSecretVersion() calls Signed-off-by: Julien Loctaux * refacto: use GetSecret with name instead of ListSecrets Signed-off-by: Julien Loctaux * feat: allow using secret name in ExternalSecrets Signed-off-by: Julien Loctaux * feat: use latest_enabled instead of latest Signed-off-by: Julien Loctaux * refacto: optimized PushSecret and improved its test coverage Signed-off-by: Julien Loctaux * fix: doesConfigDependOnNamespace was always true Signed-off-by: Julien Loctaux * feat: use new api with refactored name-based endpoints Signed-off-by: Julien Loctaux * remove useless todo Signed-off-by: Julien Loctaux * fix: use secret names as key for GetAllSecrets Signed-off-by: Julien Loctaux * feat: support gjson propery lookup Signed-off-by: Julien Loctaux * feat: e2e tests Signed-off-by: Julien Loctaux * test: e2e test using secret to store api key Signed-off-by: Julien Loctaux * test: cleanup left over resources on the secret manager before each e2e run Signed-off-by: Julien Loctaux * doc: add doc for scaleway provider Signed-off-by: Julien Loctaux * refacto: fix lint issues Signed-off-by: Julien Loctaux * test: cleanup code in e2e was commented Signed-off-by: Julien Loctaux * feat: the previous version is disabled when we push to a secret Signed-off-by: Julien Loctaux * doc: add comments to ScalewayProvider struct to point to console and doc Signed-off-by: Julien Loctaux * feat: add missing e2e env vars for scaleway Signed-off-by: Moritz Johner * docs: add scaleway to support/stability table Signed-off-by: Moritz Johner --------- Signed-off-by: Julien Loctaux Signed-off-by: Moritz Johner Co-authored-by: Moritz Johner --- .github/workflows/e2e.yml | 6 +- .../v1beta1/secretstore_scaleway_types.go | 47 ++ .../v1beta1/secretstore_types.go | 4 + .../v1beta1/zz_generated.deepcopy.go | 50 ++ ...ternal-secrets.io_clustersecretstores.yaml | 74 +++ .../external-secrets.io_secretstores.yaml | 74 +++ deploy/crds/bundle.yaml | 116 +++++ docs/api/spec.md | 136 ++++++ docs/introduction/stability-support.md | 2 + docs/provider/scaleway.md | 50 ++ e2e/framework/framework.go | 5 +- e2e/go.mod | 1 + e2e/go.sum | 2 + e2e/run.sh | 5 + e2e/suites/provider/cases/common/common.go | 111 +++-- .../provider/cases/common/find_by_name.go | 12 +- .../provider/cases/common/find_by_tags.go | 6 +- e2e/suites/provider/cases/import.go | 1 + e2e/suites/provider/cases/scaleway/config.go | 56 +++ .../provider/cases/scaleway/provider.go | 106 +++++ .../provider/cases/scaleway/scaleway.go | 121 +++++ go.mod | 1 + go.sum | 4 +- hack/api-docs/mkdocs.yml | 1 + pkg/generator/register/register.go | 1 + pkg/provider/register/register.go | 2 + pkg/provider/scaleway/cache.go | 97 ++++ pkg/provider/scaleway/cache_test.go | 63 +++ pkg/provider/scaleway/client.go | 444 ++++++++++++++++++ pkg/provider/scaleway/client_test.go | 386 +++++++++++++++ pkg/provider/scaleway/fake_secret_api_test.go | 441 +++++++++++++++++ pkg/provider/scaleway/provider.go | 195 ++++++++ pkg/provider/scaleway/secret_api.go | 32 ++ 33 files changed, 2595 insertions(+), 57 deletions(-) create mode 100644 apis/externalsecrets/v1beta1/secretstore_scaleway_types.go create mode 100644 docs/provider/scaleway.md create mode 100644 e2e/suites/provider/cases/scaleway/config.go create mode 100644 e2e/suites/provider/cases/scaleway/provider.go create mode 100644 e2e/suites/provider/cases/scaleway/scaleway.go create mode 100644 pkg/provider/scaleway/cache.go create mode 100644 pkg/provider/scaleway/cache_test.go create mode 100644 pkg/provider/scaleway/client.go create mode 100644 pkg/provider/scaleway/client_test.go create mode 100644 pkg/provider/scaleway/fake_secret_api_test.go create mode 100644 pkg/provider/scaleway/provider.go create mode 100644 pkg/provider/scaleway/secret_api.go diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 01b39528501..6d786cdee86 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -36,7 +36,11 @@ env: AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET}} TENANT_ID: ${{ secrets.TENANT_ID}} VAULT_URL: ${{ secrets.VAULT_URL}} - + SCALEWAY_API_URL: ${{ secrets.SCALEWAY_API_URL }} + SCALEWAY_REGION: ${{ secrets.SCALEWAY_REGION }} + SCALEWAY_PROJECT_ID: ${{ secrets.SCALEWAY_PROJECT_ID }} + SCALEWAY_ACCESS_KEY: ${{ secrets.SCALEWAY_ACCESS_KEY }} + SCALEWAY_SECRET_KEY: ${{ secrets.SCALEWAY_SECRET_KEY }} jobs: diff --git a/apis/externalsecrets/v1beta1/secretstore_scaleway_types.go b/apis/externalsecrets/v1beta1/secretstore_scaleway_types.go new file mode 100644 index 00000000000..9f67e9417aa --- /dev/null +++ b/apis/externalsecrets/v1beta1/secretstore_scaleway_types.go @@ -0,0 +1,47 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" + +type ScalewayProviderSecretRef struct { + + // Value can be specified directly to set a value without using a secret. + // +optional + Value string `json:"value,omitempty"` + + // SecretRef references a key in a secret that will be used as value. + // +optional + SecretRef *esmeta.SecretKeySelector `json:"secretRef,omitempty"` +} + +type ScalewayProvider struct { + + // APIURL is the url of the api to use. Defaults to https://api.scaleway.com + // +optional + APIURL string `json:"apiUrl,omitempty"` + + // Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone + Region string `json:"region"` + + // ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings + ProjectID string `json:"projectId"` + + // AccessKey is the non-secret part of the api key. + AccessKey *ScalewayProviderSecretRef `json:"accessKey"` + + // SecretKey is the non-secret part of the api key. + SecretKey *ScalewayProviderSecretRef `json:"secretKey"` +} diff --git a/apis/externalsecrets/v1beta1/secretstore_types.go b/apis/externalsecrets/v1beta1/secretstore_types.go index caae91fa1c1..d215f75bd86 100644 --- a/apis/externalsecrets/v1beta1/secretstore_types.go +++ b/apis/externalsecrets/v1beta1/secretstore_types.go @@ -121,6 +121,10 @@ type SecretStoreProvider struct { // +optional Senhasegura *SenhaseguraProvider `json:"senhasegura,omitempty"` + // Scaleway + // +optional + Scaleway *ScalewayProvider `json:"scaleway,omitempty"` + // Doppler configures this store to sync secrets using the Doppler provider // +optional Doppler *DopplerProvider `json:"doppler,omitempty"` diff --git a/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go b/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go index 101493141a6..483facd3f3d 100644 --- a/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go +++ b/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go @@ -1520,6 +1520,51 @@ func (in *OracleSecretRef) DeepCopy() *OracleSecretRef { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScalewayProvider) DeepCopyInto(out *ScalewayProvider) { + *out = *in + if in.AccessKey != nil { + in, out := &in.AccessKey, &out.AccessKey + *out = new(ScalewayProviderSecretRef) + (*in).DeepCopyInto(*out) + } + if in.SecretKey != nil { + in, out := &in.SecretKey, &out.SecretKey + *out = new(ScalewayProviderSecretRef) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScalewayProvider. +func (in *ScalewayProvider) DeepCopy() *ScalewayProvider { + if in == nil { + return nil + } + out := new(ScalewayProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScalewayProviderSecretRef) DeepCopyInto(out *ScalewayProviderSecretRef) { + *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + *out = new(metav1.SecretKeySelector) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScalewayProviderSecretRef. +func (in *ScalewayProviderSecretRef) DeepCopy() *ScalewayProviderSecretRef { + if in == nil { + return nil + } + out := new(ScalewayProviderSecretRef) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecretStore) DeepCopyInto(out *SecretStore) { *out = *in @@ -1662,6 +1707,11 @@ func (in *SecretStoreProvider) DeepCopyInto(out *SecretStoreProvider) { *out = new(SenhaseguraProvider) (*in).DeepCopyInto(*out) } + if in.Scaleway != nil { + in, out := &in.Scaleway, &out.Scaleway + *out = new(ScalewayProvider) + (*in).DeepCopyInto(*out) + } if in.Doppler != nil { in, out := &in.Doppler, &out.Doppler *out = new(DopplerProvider) diff --git a/config/crds/bases/external-secrets.io_clustersecretstores.yaml b/config/crds/bases/external-secrets.io_clustersecretstores.yaml index 6c1c7870a9a..91d3ff7c4e6 100644 --- a/config/crds/bases/external-secrets.io_clustersecretstores.yaml +++ b/config/crds/bases/external-secrets.io_clustersecretstores.yaml @@ -2749,6 +2749,80 @@ spec: - region - vault type: object + scaleway: + description: Scaleway + properties: + accessKey: + description: AccessKey is the non-secret part of the api key. + properties: + secretRef: + description: SecretRef references a key in a secret that + will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a + value without using a secret. + type: string + type: object + apiUrl: + description: APIURL is the url of the api to use. Defaults + to https://api.scaleway.com + type: string + projectId: + description: 'ProjectID is the id of your project, which you + can find in the console: https://console.scaleway.com/project/settings' + type: string + region: + description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' + type: string + secretKey: + description: SecretKey is the non-secret part of the api key. + properties: + secretRef: + description: SecretRef references a key in a secret that + will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a + value without using a secret. + type: string + type: object + required: + - accessKey + - projectId + - region + - secretKey + type: object senhasegura: description: Senhasegura configures this store to sync secrets using senhasegura provider diff --git a/config/crds/bases/external-secrets.io_secretstores.yaml b/config/crds/bases/external-secrets.io_secretstores.yaml index c6a6d6c4059..b3dbd06e3bb 100644 --- a/config/crds/bases/external-secrets.io_secretstores.yaml +++ b/config/crds/bases/external-secrets.io_secretstores.yaml @@ -2749,6 +2749,80 @@ spec: - region - vault type: object + scaleway: + description: Scaleway + properties: + accessKey: + description: AccessKey is the non-secret part of the api key. + properties: + secretRef: + description: SecretRef references a key in a secret that + will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a + value without using a secret. + type: string + type: object + apiUrl: + description: APIURL is the url of the api to use. Defaults + to https://api.scaleway.com + type: string + projectId: + description: 'ProjectID is the id of your project, which you + can find in the console: https://console.scaleway.com/project/settings' + type: string + region: + description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' + type: string + secretKey: + description: SecretKey is the non-secret part of the api key. + properties: + secretRef: + description: SecretRef references a key in a secret that + will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this + field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: Namespace of the resource being referred + to. Ignored if referent is not cluster-scoped. cluster-scoped + defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a + value without using a secret. + type: string + type: object + required: + - accessKey + - projectId + - region + - secretKey + type: object senhasegura: description: Senhasegura configures this store to sync secrets using senhasegura provider diff --git a/deploy/crds/bundle.yaml b/deploy/crds/bundle.yaml index 0ed223e9a15..338adf538c0 100644 --- a/deploy/crds/bundle.yaml +++ b/deploy/crds/bundle.yaml @@ -2462,6 +2462,64 @@ spec: - region - vault type: object + scaleway: + description: Scaleway + properties: + accessKey: + description: AccessKey is the non-secret part of the api key. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + apiUrl: + description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com + type: string + projectId: + description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' + type: string + region: + description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' + type: string + secretKey: + description: SecretKey is the non-secret part of the api key. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + required: + - accessKey + - projectId + - region + - secretKey + type: object senhasegura: description: Senhasegura configures this store to sync secrets using senhasegura provider properties: @@ -5829,6 +5887,64 @@ spec: - region - vault type: object + scaleway: + description: Scaleway + properties: + accessKey: + description: AccessKey is the non-secret part of the api key. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + apiUrl: + description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com + type: string + projectId: + description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' + type: string + region: + description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' + type: string + secretKey: + description: SecretKey is the non-secret part of the api key. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + required: + - accessKey + - projectId + - region + - secretKey + type: object senhasegura: description: Senhasegura configures this store to sync secrets using senhasegura provider properties: diff --git a/docs/api/spec.md b/docs/api/spec.md index 203166c2f4e..69d5fc180fc 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -3955,6 +3955,128 @@ External Secrets meta/v1.SecretKeySelector

This interface is to allow using v1alpha1 content in Provider registered in v1beta1.

+

ScalewayProvider +

+

+(Appears on: +SecretStoreProvider) +

+

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+apiUrl
+ +string + +
+(Optional) +

APIURL is the url of the api to use. Defaults to https://api.scaleway.com

+
+region
+ +string + +
+

Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone

+
+projectId
+ +string + +
+

ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings

+
+accessKey
+ + +ScalewayProviderSecretRef + + +
+

AccessKey is the non-secret part of the api key.

+
+secretKey
+ + +ScalewayProviderSecretRef + + +
+

SecretKey is the non-secret part of the api key.

+
+

ScalewayProviderSecretRef +

+

+(Appears on: +ScalewayProvider) +

+

+

+ + + + + + + + + + + + + + + + + +
FieldDescription
+value
+ +string + +
+(Optional) +

Value can be specified directly to set a value without using a secret.

+
+secretRef
+ + +External Secrets meta/v1.SecretKeySelector + + +
+(Optional) +

SecretRef references a key in a secret that will be used as value.

+

SecretStore

@@ -4364,6 +4486,20 @@ SenhaseguraProvider +scaleway
+ + +ScalewayProvider + + + + +(Optional) +

Scaleway

+ + + + doppler
diff --git a/docs/introduction/stability-support.md b/docs/introduction/stability-support.md index f99c2f914be..ad50fb25a29 100644 --- a/docs/introduction/stability-support.md +++ b/docs/introduction/stability-support.md @@ -41,6 +41,7 @@ The following table describes the stability level of each provider and who's res | [senhasegura DevOps Secrets Management (DSM)](https://external-secrets.io/latest/provider/senhasegura-dsm) | alpha | [@lfraga](https://github.com/lfraga) | | [Doppler SecretOps Platform](https://external-secrets.io/latest/provider/doppler) | alpha | [@ryan-blunden](https://github.com/ryan-blunden/) [@nmanoogian](https://github.com/nmanoogian/) | | [Keeper Security](https://www.keepersecurity.com/) | alpha | [@ppodevlab](https://github.com/ppodevlab) | +| [Scaleway](https://external-secrets.io/latest/provider/scaleway) | alpha | [@azert9](https://github.com/azert9/) | ## Provider Feature Support @@ -65,6 +66,7 @@ The following table show the support for features across different providers. | senhasegura DSM | | | | | x | | | | Doppler | x | | | | x | | | | Keeper Security | x | | | | x | x | | +| Scaleway | x | x | | | x | x | x | ## Support Policy diff --git a/docs/provider/scaleway.md b/docs/provider/scaleway.md new file mode 100644 index 00000000000..ff6518bc122 --- /dev/null +++ b/docs/provider/scaleway.md @@ -0,0 +1,50 @@ +## Scaleway Secret Manager + +External Secrets Operator integrates with [Scaleway's Secret Manager](https://developers.scaleway.com/en/products/secret_manager/api/v1alpha1/). + +### Creating a SecretStore + +You need an api key (access key + secret key) to authenticate with the secret manager. +Both access and secret keys can be specified either directly in the config, or by referencing +a kubernetes secret. + +```yaml +apiVersion: external-secrets.io/v1beta1 +kind: SecretStore +metadata: + name: secret-store +spec: + provider: + scaleway: + region: + projectId: + accessKey: + value: + secretKey: + secretRef: + name: + key: +``` + +### Referencing Secrets + +Secrets can be referenced by name or by id, using the prefixes `"name:"` and `"id:"` respectively. + +A PushSecret resource can only use a name reference. + +```yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: secret +spec: + refreshInterval: 20s + secretStoreRef: + kind: SecretStore + name: secret-store + data: + - secretKey: + remoteRef: + key: id: + version: latest_enabled +``` diff --git a/e2e/framework/framework.go b/e2e/framework/framework.go index 0d3da1ab94d..df99cdc1ab8 100644 --- a/e2e/framework/framework.go +++ b/e2e/framework/framework.go @@ -46,12 +46,15 @@ type Framework struct { Namespace *api.Namespace Addons []addon.Addon + + MakeRemoteRefKey func(base string) string } // New returns a new framework instance with defaults. func New(baseName string) *Framework { f := &Framework{ - BaseName: baseName, + BaseName: baseName, + MakeRemoteRefKey: func(base string) string { return base }, } f.KubeConfig, f.KubeClientSet, f.CRClient = util.NewConfig() diff --git a/e2e/go.mod b/e2e/go.mod index df584761719..e7ccd3d3a46 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -55,6 +55,7 @@ require ( github.com/onsi/ginkgo/v2 v2.9.1 github.com/onsi/gomega v1.27.3 github.com/oracle/oci-go-sdk/v56 v56.1.0 + github.com/scaleway/scaleway-sdk-go v1.0.0-beta.13.0.20230227165516-144b3e06ecf2 github.com/xanzy/go-gitlab v0.81.0 golang.org/x/oauth2 v0.6.0 google.golang.org/api v0.112.0 diff --git a/e2e/go.sum b/e2e/go.sum index e64af6b39e8..f83ca5adebd 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -859,6 +859,8 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.13.0.20230227165516-144b3e06ecf2 h1:LyHBuaec79FY+tmMHUdnctd/es78NzZ7VKcE2QmdPTc= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.13.0.20230227165516-144b3e06ecf2/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= diff --git a/e2e/run.sh b/e2e/run.sh index b2bac693871..5b83549349a 100755 --- a/e2e/run.sh +++ b/e2e/run.sh @@ -73,6 +73,11 @@ kubectl run --rm \ --env="ORACLE_REGION=${ORACLE_REGION:-}" \ --env="ORACLE_FINGERPRINT=${ORACLE_FINGERPRINT:-}" \ --env="ORACLE_KEY=${ORACLE_KEY:-}" \ + --env="SCALEWAY_API_URL=${SCALEWAY_API_URL:-}" \ + --env="SCALEWAY_REGION=${SCALEWAY_REGION:-}" \ + --env="SCALEWAY_PROJECT_ID=${SCALEWAY_PROJECT_ID:-}" \ + --env="SCALEWAY_ACCESS_KEY=${SCALEWAY_ACCESS_KEY:-}" \ + --env="SCALEWAY_SECRET_KEY=${SCALEWAY_SECRET_KEY:-}" \ --env="VERSION=${VERSION}" \ --env="TEST_SUITES=${TEST_SUITES}" \ --overrides='{ "apiVersion": "v1", "spec":{"serviceAccountName": "external-secrets-e2e"}}' \ diff --git a/e2e/suites/provider/cases/common/common.go b/e2e/suites/provider/cases/common/common.go index 304d85bece3..cf2b9da5c8d 100644 --- a/e2e/suites/provider/cases/common/common.go +++ b/e2e/suites/provider/cases/common/common.go @@ -87,10 +87,12 @@ func SimpleDataSync(f *framework.Framework) (string, func(*framework.TestCase)) return "[common] should sync simple secrets from .Data[]", func(tc *framework.TestCase) { secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one") secretKey2 := fmt.Sprintf("%s-%s", f.Namespace.Name, "other") + remoteRefKey1 := f.MakeRemoteRefKey(secretKey1) + remoteRefKey2 := f.MakeRemoteRefKey(secretKey2) secretValue := "bar" tc.Secrets = map[string]framework.SecretEntry{ - secretKey1: {Value: secretValue}, - secretKey2: {Value: secretValue}, + remoteRefKey1: {Value: secretValue}, + remoteRefKey2: {Value: secretValue}, } tc.ExpectedSecret = &v1.Secret{ Type: v1.SecretTypeOpaque, @@ -103,13 +105,13 @@ func SimpleDataSync(f *framework.Framework) (string, func(*framework.TestCase)) { SecretKey: secretKey1, RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey1, + Key: remoteRefKey1, }, }, { SecretKey: secretKey2, RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey2, + Key: remoteRefKey2, }, }, } @@ -121,9 +123,10 @@ func SimpleDataSync(f *framework.Framework) (string, func(*framework.TestCase)) func SyncWithoutTargetName(f *framework.Framework) (string, func(*framework.TestCase)) { return "[common] should sync with empty target name.", func(tc *framework.TestCase) { secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one") + remoteRefKey1 := f.MakeRemoteRefKey(secretKey1) secretValue := "bar" tc.Secrets = map[string]framework.SecretEntry{ - secretKey1: {Value: secretValue}, + remoteRefKey1: {Value: secretValue}, } tc.ExpectedSecret = &v1.Secret{ Type: v1.SecretTypeOpaque, @@ -136,7 +139,7 @@ func SyncWithoutTargetName(f *framework.Framework) (string, func(*framework.Test { SecretKey: secretKey1, RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey1, + Key: remoteRefKey1, }, }, } @@ -149,9 +152,11 @@ func JSONDataWithProperty(f *framework.Framework) (string, func(*framework.TestC return "[common] should sync multiple secrets from .Data[]", func(tc *framework.TestCase) { secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one") secretKey2 := fmt.Sprintf("%s-%s", f.Namespace.Name, "two") + remoteRefKey1 := f.MakeRemoteRefKey(secretKey1) + remoteRefKey2 := f.MakeRemoteRefKey(secretKey2) tc.Secrets = map[string]framework.SecretEntry{ - secretKey1: {Value: secretValue1}, - secretKey2: {Value: secretValue2}, + remoteRefKey1: {Value: secretValue1}, + remoteRefKey2: {Value: secretValue2}, } tc.ExpectedSecret = &v1.Secret{ Type: v1.SecretTypeOpaque, @@ -164,14 +169,14 @@ func JSONDataWithProperty(f *framework.Framework) (string, func(*framework.TestC { SecretKey: secretKey1, RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey1, + Key: remoteRefKey1, Property: "foo1", }, }, { SecretKey: secretKey2, RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey2, + Key: remoteRefKey2, Property: "bar2", }, }, @@ -184,9 +189,10 @@ func JSONDataWithProperty(f *framework.Framework) (string, func(*framework.TestC func JSONDataWithoutTargetName(f *framework.Framework) (string, func(*framework.TestCase)) { return "[common] should sync with empty target name, using json.", func(tc *framework.TestCase) { secretKey := fmt.Sprintf("%s-%s", f.Namespace.Name, "one") + remoteRefKey := f.MakeRemoteRefKey(secretKey) secretValue := "{\"foo\":\"foo-val\",\"bar\":\"bar-val\"}" tc.Secrets = map[string]framework.SecretEntry{ - secretKey: {Value: secretValue}, + remoteRefKey: {Value: secretValue}, } tc.ExpectedSecret = &v1.Secret{ Type: v1.SecretTypeOpaque, @@ -199,7 +205,7 @@ func JSONDataWithoutTargetName(f *framework.Framework) (string, func(*framework. { SecretKey: secretKey, RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey, + Key: remoteRefKey, Property: "foo", }, }, @@ -213,9 +219,11 @@ func JSONDataWithTemplate(f *framework.Framework) (string, func(*framework.TestC return "[common] should sync json secrets with template", func(tc *framework.TestCase) { secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one") secretKey2 := fmt.Sprintf("%s-%s", f.Namespace.Name, "other") + remoteRefKey1 := f.MakeRemoteRefKey(secretKey1) + remoteRefKey2 := f.MakeRemoteRefKey(secretKey2) tc.Secrets = map[string]framework.SecretEntry{ - secretKey1: {Value: secretValue1}, - secretKey2: {Value: secretValue2}, + remoteRefKey1: {Value: secretValue1}, + remoteRefKey2: {Value: secretValue2}, } tc.ExpectedSecret = &v1.Secret{ Type: v1.SecretTypeOpaque, @@ -248,14 +256,14 @@ func JSONDataWithTemplate(f *framework.Framework) (string, func(*framework.TestC { SecretKey: "one", RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey1, + Key: remoteRefKey1, Property: "foo1", }, }, { SecretKey: "two", RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey2, + Key: remoteRefKey2, Property: "bar2", }, }, @@ -269,9 +277,11 @@ func JSONDataWithTemplateFromLiteral(f *framework.Framework) (string, func(*fram return "[common] should sync json secrets with template", func(tc *framework.TestCase) { secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one") secretKey2 := fmt.Sprintf("%s-%s", f.Namespace.Name, "other") + remoteRefKey1 := f.MakeRemoteRefKey(secretKey1) + remoteRefKey2 := f.MakeRemoteRefKey(secretKey2) tc.Secrets = map[string]framework.SecretEntry{ - secretKey1: {Value: secretValue1}, - secretKey2: {Value: secretValue2}, + remoteRefKey1: {Value: secretValue1}, + remoteRefKey2: {Value: secretValue2}, } tc.ExpectedSecret = &v1.Secret{ Type: v1.SecretTypeOpaque, @@ -292,14 +302,14 @@ func JSONDataWithTemplateFromLiteral(f *framework.Framework) (string, func(*fram { SecretKey: "one", RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey1, + Key: remoteRefKey1, Property: "foo1", }, }, { SecretKey: "two", RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey2, + Key: remoteRefKey2, Property: "bar2", }, }, @@ -313,6 +323,8 @@ func TemplateFromConfigmaps(f *framework.Framework) (string, func(*framework.Tes return "[common] should sync from templateFrom Configmaps", func(tc *framework.TestCase) { secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one") secretKey2 := fmt.Sprintf("%s-%s", f.Namespace.Name, "other") + remoteRefKey1 := f.MakeRemoteRefKey(secretKey1) + remoteRefKey2 := f.MakeRemoteRefKey(secretKey2) tc.AdditionalObjects = []client.Object{ &v1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ @@ -326,8 +338,8 @@ func TemplateFromConfigmaps(f *framework.Framework) (string, func(*framework.Tes }, } tc.Secrets = map[string]framework.SecretEntry{ - secretKey1: {Value: secretValue1}, - secretKey2: {Value: secretValue2}, + remoteRefKey1: {Value: secretValue1}, + remoteRefKey2: {Value: secretValue2}, } tc.ExpectedSecret = &v1.Secret{ Type: v1.SecretTypeOpaque, @@ -360,14 +372,14 @@ func TemplateFromConfigmaps(f *framework.Framework) (string, func(*framework.Tes { SecretKey: "one", RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey1, + Key: remoteRefKey1, Property: "foo1", }, }, { SecretKey: "two", RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey2, + Key: remoteRefKey2, Property: "bar2", }, }, @@ -379,13 +391,14 @@ func TemplateFromConfigmaps(f *framework.Framework) (string, func(*framework.Tes func JSONDataFromSync(f *framework.Framework) (string, func(*framework.TestCase)) { return "[common] should sync secrets with dataFrom", func(tc *framework.TestCase) { secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one") + remoteRefKey1 := f.MakeRemoteRefKey(secretKey1) targetSecretKey1 := "name" targetSecretValue1 := "great-name" targetSecretKey2 := "surname" targetSecretValue2 := "great-surname" secretValue := fmt.Sprintf("{ %q: %q, %q: %q }", targetSecretKey1, targetSecretValue1, targetSecretKey2, targetSecretValue2) tc.Secrets = map[string]framework.SecretEntry{ - secretKey1: {Value: secretValue}, + remoteRefKey1: {Value: secretValue}, } tc.ExpectedSecret = &v1.Secret{ Type: v1.SecretTypeOpaque, @@ -397,7 +410,7 @@ func JSONDataFromSync(f *framework.Framework) (string, func(*framework.TestCase) tc.ExternalSecret.Spec.DataFrom = []esv1beta1.ExternalSecretDataFromRemoteRef{ { Extract: &esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey1, + Key: remoteRefKey1, }, }, } @@ -408,13 +421,14 @@ func JSONDataFromSync(f *framework.Framework) (string, func(*framework.TestCase) func JSONDataFromRewrite(f *framework.Framework) (string, func(*framework.TestCase)) { return "[common] should sync and rewrite secrets with dataFrom", func(tc *framework.TestCase) { secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one") + remoteRefKey1 := f.MakeRemoteRefKey(secretKey1) targetSecretKey1 := "username" targetSecretValue1 := "myuser.name" targetSecretKey2 := "address" targetSecretValue2 := "happy street" secretValue := fmt.Sprintf("{ %q: %q, %q: %q }", targetSecretKey1, targetSecretValue1, targetSecretKey2, targetSecretValue2) tc.Secrets = map[string]framework.SecretEntry{ - secretKey1: {Value: secretValue}, + remoteRefKey1: {Value: secretValue}, } tc.ExpectedSecret = &v1.Secret{ Type: v1.SecretTypeOpaque, @@ -426,7 +440,7 @@ func JSONDataFromRewrite(f *framework.Framework) (string, func(*framework.TestCa tc.ExternalSecret.Spec.DataFrom = []esv1beta1.ExternalSecretDataFromRemoteRef{ { Extract: &esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey1, + Key: remoteRefKey1, }, Rewrite: []esv1beta1.ExternalSecretRewrite{ { @@ -447,6 +461,7 @@ func JSONDataFromRewrite(f *framework.Framework) (string, func(*framework.TestCa func NestedJSONWithGJSON(f *framework.Framework) (string, func(*framework.TestCase)) { return "[common] should sync nested json secrets and get inner keys", func(tc *framework.TestCase) { secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one") + remoteRefKey1 := f.MakeRemoteRefKey(secretKey1) targetSecretKey1 := "firstname" targetSecretValue1 := "Tom" targetSecretKey2 := "first_friend" @@ -462,7 +477,7 @@ func NestedJSONWithGJSON(f *framework.Framework) (string, func(*framework.TestCa ] }`, targetSecretValue1, targetSecretValue2) tc.Secrets = map[string]framework.SecretEntry{ - secretKey1: {Value: secretValue}, + remoteRefKey1: {Value: secretValue}, } tc.ExpectedSecret = &v1.Secret{ Type: v1.SecretTypeOpaque, @@ -475,14 +490,14 @@ func NestedJSONWithGJSON(f *framework.Framework) (string, func(*framework.TestCa { SecretKey: targetSecretKey1, RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey1, + Key: remoteRefKey1, Property: "name.first", }, }, { SecretKey: targetSecretKey2, RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey1, + Key: remoteRefKey1, Property: "friends.1.first", }, }, @@ -496,10 +511,11 @@ func NestedJSONWithGJSON(f *framework.Framework) (string, func(*framework.TestCa func DockerJSONConfig(f *framework.Framework) (string, func(*framework.TestCase)) { return "[common] should sync docker configurated json secrets with template simple", func(tc *framework.TestCase) { cloudSecretName := fmt.Sprintf("%s-%s", f.Namespace.Name, dockerConfigExampleName) + cloudRemoteRefKey := f.MakeRemoteRefKey(cloudSecretName) dockerconfig := `{"auths":{"https://index.docker.io/v1/": {"auth": "c3R...zE2"}}}` cloudSecretValue := fmt.Sprintf(`{"dockerconfig": %s}`, dockerconfig) tc.Secrets = map[string]framework.SecretEntry{ - cloudSecretName: {Value: cloudSecretValue}, + cloudRemoteRefKey: {Value: cloudSecretValue}, } tc.ExpectedSecret = &v1.Secret{ @@ -513,7 +529,7 @@ func DockerJSONConfig(f *framework.Framework) (string, func(*framework.TestCase) { SecretKey: "mysecret", RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: cloudSecretName, + Key: cloudRemoteRefKey, Property: "dockerconfig", }, }, @@ -533,11 +549,12 @@ func DockerJSONConfig(f *framework.Framework) (string, func(*framework.TestCase) func DataPropertyDockerconfigJSON(f *framework.Framework) (string, func(*framework.TestCase)) { return "[common] should sync docker configurated json secrets with template", func(tc *framework.TestCase) { cloudSecretName := fmt.Sprintf("%s-%s", f.Namespace.Name, dockerConfigExampleName) + cloudRemoteRefKey := f.MakeRemoteRefKey(cloudSecretName) dockerconfigString := `"{\"auths\":{\"https://index.docker.io/v1/\": {\"auth\": \"c3R...zE2\"}}}"` dockerconfig := `{"auths":{"https://index.docker.io/v1/": {"auth": "c3R...zE2"}}}` cloudSecretValue := fmt.Sprintf(`{"dockerconfig": %s}`, dockerconfigString) tc.Secrets = map[string]framework.SecretEntry{ - cloudSecretName: {Value: cloudSecretValue}, + cloudRemoteRefKey: {Value: cloudSecretValue}, } tc.ExpectedSecret = &v1.Secret{ @@ -551,7 +568,7 @@ func DataPropertyDockerconfigJSON(f *framework.Framework) (string, func(*framewo { SecretKey: "mysecret", RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: cloudSecretName, + Key: cloudRemoteRefKey, Property: "dockerconfig", }, }, @@ -609,9 +626,10 @@ func SSHKeySync(f *framework.Framework) (string, func(*framework.TestCase)) { PKDc8xGEXdd4A6jnwJBifJs+UpPrHAh0c63KfjO3rryDycvmxeWRnyU1yRCUjIuH31vi+L OkcGfqTaOoz2KVAAAAFGtpYW5AREVTS1RPUC1TNFI5S1JQAQIDBAUG -----END OPENSSH PRIVATE KEY-----` + sshRemoteRefKey := f.MakeRemoteRefKey(sshSecretName) tc.Secrets = map[string]framework.SecretEntry{ - sshSecretName: {Value: sshSecretValue}, + sshRemoteRefKey: {Value: sshSecretValue}, } tc.ExpectedSecret = &v1.Secret{ @@ -625,7 +643,7 @@ func SSHKeySync(f *framework.Framework) (string, func(*framework.TestCase)) { { SecretKey: "mysecret", RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: sshSecretName, + Key: sshRemoteRefKey, }, }, } @@ -643,6 +661,7 @@ func SSHKeySync(f *framework.Framework) (string, func(*framework.TestCase)) { func SSHKeySyncDataProperty(f *framework.Framework) (string, func(*framework.TestCase)) { return "[common] should sync ssh key with provider.", func(tc *framework.TestCase) { cloudSecretName := fmt.Sprintf("%s-%s", f.Namespace.Name, dockerConfigExampleName) + cloudRemoteRefKey := f.MakeRemoteRefKey(cloudSecretName) SSHKey := `-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn NhAAAAAwEAAQAAAYEAsARoZUqo6L5dd0WRjZ2QPq/kKlbjtUY1njzJ01UtdC1u1eSJFUnV @@ -683,7 +702,7 @@ func SSHKeySyncDataProperty(f *framework.Framework) (string, func(*framework.Tes -----END OPENSSH PRIVATE KEY-----` cloudSecretValue := fmt.Sprintf(`{"ssh-auth": %q}`, SSHKey) tc.Secrets = map[string]framework.SecretEntry{ - cloudSecretName: {Value: cloudSecretValue}, + cloudRemoteRefKey: {Value: cloudSecretValue}, } tc.ExpectedSecret = &v1.Secret{ @@ -697,7 +716,7 @@ func SSHKeySyncDataProperty(f *framework.Framework) (string, func(*framework.Tes { SecretKey: "mysecret", RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: cloudSecretName, + Key: cloudRemoteRefKey, Property: "ssh-auth", }, }, @@ -716,10 +735,12 @@ func DeletionPolicyDelete(f *framework.Framework) (string, func(*framework.TestC return "[common] should delete secret when provider secret was deleted using .data[]", func(tc *framework.TestCase) { secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one") secretKey2 := fmt.Sprintf("%s-%s", f.Namespace.Name, "other") + remoteRefKey1 := f.MakeRemoteRefKey(secretKey1) + remoteRefKey2 := f.MakeRemoteRefKey(secretKey2) secretValue := "bazz" tc.Secrets = map[string]framework.SecretEntry{ - secretKey1: {Value: secretValue}, - secretKey2: {Value: secretValue}, + remoteRefKey1: {Value: secretValue}, + remoteRefKey2: {Value: secretValue}, } tc.ExpectedSecret = &v1.Secret{ Type: v1.SecretTypeOpaque, @@ -734,19 +755,19 @@ func DeletionPolicyDelete(f *framework.Framework) (string, func(*framework.TestC { SecretKey: secretKey1, RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey1, + Key: remoteRefKey1, }, }, { SecretKey: secretKey2, RemoteRef: esv1beta1.ExternalSecretDataRemoteRef{ - Key: secretKey2, + Key: remoteRefKey2, }, }, } tc.AfterSync = func(prov framework.SecretStoreProvider, secret *v1.Secret) { - prov.DeleteSecret(secretKey1) - prov.DeleteSecret(secretKey2) + prov.DeleteSecret(remoteRefKey1) + prov.DeleteSecret(remoteRefKey2) gomega.Eventually(func() bool { _, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.Background(), secret.Name, metav1.GetOptions{}) diff --git a/e2e/suites/provider/cases/common/find_by_name.go b/e2e/suites/provider/cases/common/find_by_name.go index 620d2bdac8a..42960527f72 100644 --- a/e2e/suites/provider/cases/common/find_by_name.go +++ b/e2e/suites/provider/cases/common/find_by_name.go @@ -34,9 +34,9 @@ func FindByName(f *framework.Framework) (string, func(*framework.TestCase)) { secretKeyThree := fmt.Sprintf(namePrefix, f.Namespace.Name, "three") secretValue := findValue tc.Secrets = map[string]framework.SecretEntry{ - secretKeyOne: {Value: secretValue}, - secretKeyTwo: {Value: secretValue}, - secretKeyThree: {Value: secretValue}, + f.MakeRemoteRefKey(secretKeyOne): {Value: secretValue}, + f.MakeRemoteRefKey(secretKeyTwo): {Value: secretValue}, + f.MakeRemoteRefKey(secretKeyThree): {Value: secretValue}, } tc.ExpectedSecret = &v1.Secret{ Type: v1.SecretTypeOpaque, @@ -70,9 +70,9 @@ func FindByNameAndRewrite(f *framework.Framework) (string, func(*framework.TestC expectedKeyThree := fmt.Sprintf("%s_%s", f.Namespace.Name, "three") secretValue := findValue tc.Secrets = map[string]framework.SecretEntry{ - secretKeyOne: {Value: secretValue}, - secretKeyTwo: {Value: secretValue}, - secretKeyThree: {Value: secretValue}, + f.MakeRemoteRefKey(secretKeyOne): {Value: secretValue}, + f.MakeRemoteRefKey(secretKeyTwo): {Value: secretValue}, + f.MakeRemoteRefKey(secretKeyThree): {Value: secretValue}, } tc.ExpectedSecret = &v1.Secret{ Type: v1.SecretTypeOpaque, diff --git a/e2e/suites/provider/cases/common/find_by_tags.go b/e2e/suites/provider/cases/common/find_by_tags.go index 55cd705cee2..18ec0d9af77 100644 --- a/e2e/suites/provider/cases/common/find_by_tags.go +++ b/e2e/suites/provider/cases/common/find_by_tags.go @@ -29,17 +29,17 @@ func FindByTag(f *framework.Framework) (string, func(*framework.TestCase)) { secretKeyTwo := fmt.Sprintf(namePrefix, f.Namespace.Name, "two") secretKeyThree := fmt.Sprintf(namePrefix, f.Namespace.Name, "three") tc.Secrets = map[string]framework.SecretEntry{ - secretKeyOne: { + f.MakeRemoteRefKey(secretKeyOne): { Value: secretValue1, Tags: map[string]string{ "test": f.Namespace.Name, }}, - secretKeyTwo: { + f.MakeRemoteRefKey(secretKeyTwo): { Value: secretValue1, Tags: map[string]string{ "test": f.Namespace.Name, }}, - secretKeyThree: { + f.MakeRemoteRefKey(secretKeyThree): { Value: secretValue1, Tags: map[string]string{ "test": f.Namespace.Name, diff --git a/e2e/suites/provider/cases/import.go b/e2e/suites/provider/cases/import.go index 81772500001..c3b2fd2ec3d 100644 --- a/e2e/suites/provider/cases/import.go +++ b/e2e/suites/provider/cases/import.go @@ -21,6 +21,7 @@ import ( _ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/azure" _ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/gcp" _ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/kubernetes" + _ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/scaleway" _ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/template" _ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/vault" ) diff --git a/e2e/suites/provider/cases/scaleway/config.go b/e2e/suites/provider/cases/scaleway/config.go new file mode 100644 index 00000000000..a78cf51ccd5 --- /dev/null +++ b/e2e/suites/provider/cases/scaleway/config.go @@ -0,0 +1,56 @@ +package scaleway + +import ( + "fmt" + "os" +) + +type config struct { + apiUrl *string + region string + projectId string + accessKey string + secretKey string +} + +func loadConfigFromEnv() (*config, error) { + + var cfg config + var err error + + if apiUrl, ok := os.LookupEnv("SCALEWAY_API_URL"); ok { + cfg.apiUrl = &apiUrl + } + + cfg.region, err = getEnv("SCALEWAY_REGION") + if err != nil { + return nil, err + } + + cfg.projectId, err = getEnv("SCALEWAY_PROJECT_ID") + if err != nil { + return nil, err + } + + cfg.accessKey, err = getEnv("SCALEWAY_ACCESS_KEY") + if err != nil { + return nil, err + } + + cfg.secretKey, err = getEnv("SCALEWAY_SECRET_KEY") + if err != nil { + return nil, err + } + + return &cfg, nil +} + +func getEnv(name string) (string, error) { + + value, ok := os.LookupEnv(name) + if !ok { + return "", fmt.Errorf("environment variable %q is not set", name) + } + + return value, nil +} diff --git a/e2e/suites/provider/cases/scaleway/provider.go b/e2e/suites/provider/cases/scaleway/provider.go new file mode 100644 index 00000000000..5ce21767429 --- /dev/null +++ b/e2e/suites/provider/cases/scaleway/provider.go @@ -0,0 +1,106 @@ +package scaleway + +import ( + "github.com/external-secrets/external-secrets-e2e/framework" + "github.com/onsi/gomega" + smapi "github.com/scaleway/scaleway-sdk-go/api/secret/v1alpha1" + "github.com/scaleway/scaleway-sdk-go/scw" +) + +const remoteRefPrefix = "name:" +const cleanupTag = "eso-e2e" // tag for easy cleanup + +type secretStoreProvider struct { + api *smapi.API + cfg *config +} + +func (p *secretStoreProvider) init(cfg *config) { + + p.cfg = cfg + + options := []scw.ClientOption{ + scw.WithDefaultRegion(scw.Region(cfg.region)), + scw.WithDefaultProjectID(cfg.projectId), + scw.WithAuth(cfg.accessKey, cfg.secretKey), + } + + if cfg.apiUrl != nil { + options = append(options, scw.WithAPIURL(*cfg.apiUrl)) + } + + scwClient, err := scw.NewClient(options...) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + + p.api = smapi.NewAPI(scwClient) +} + +// cleanup prevents accumulation of secrets after aborted runs. +func (p *secretStoreProvider) cleanup() { + + for { + listResp, err := p.api.ListSecrets(&smapi.ListSecretsRequest{ + ProjectID: &p.cfg.projectId, + Tags: []string{cleanupTag}, + }) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + + for _, secret := range listResp.Secrets { + err := p.api.DeleteSecret(&smapi.DeleteSecretRequest{ + SecretID: secret.ID, + }) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + } + + if uint32(len(listResp.Secrets)) == listResp.TotalCount { + break + } + } +} + +func (p *secretStoreProvider) CreateSecret(key string, val framework.SecretEntry) { + + gomega.Expect(key).To(gomega.HavePrefix(remoteRefPrefix)) + secretName := key[len(remoteRefPrefix):] + + var tags []string + for tag := range val.Tags { + tags = append(tags, tag) + } + + tags = append(tags, cleanupTag) + + secret, err := p.api.CreateSecret(&smapi.CreateSecretRequest{ + Name: secretName, + Tags: tags, + }) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + + _, err = p.api.CreateSecretVersion(&smapi.CreateSecretVersionRequest{ + SecretID: secret.ID, + Data: []byte(val.Value), + }) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) +} + +func (p *secretStoreProvider) DeleteSecret(key string) { + + gomega.Expect(key).To(gomega.HavePrefix(remoteRefPrefix)) + secretName := key[len(remoteRefPrefix):] + + secret, err := p.api.GetSecretByName(&smapi.GetSecretByNameRequest{ + SecretName: secretName, + }) + if _, isErrNotFound := err.(*scw.ResourceNotFoundError); isErrNotFound { + return + } + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + + err = p.api.DeleteSecret(&smapi.DeleteSecretRequest{ + SecretID: secret.ID, + }) + if _, isErrNotFound := err.(*scw.ResourceNotFoundError); isErrNotFound { + return + } + gomega.Expect(err).ToNot(gomega.HaveOccurred()) +} diff --git a/e2e/suites/provider/cases/scaleway/scaleway.go b/e2e/suites/provider/cases/scaleway/scaleway.go new file mode 100644 index 00000000000..d1be5deb116 --- /dev/null +++ b/e2e/suites/provider/cases/scaleway/scaleway.go @@ -0,0 +1,121 @@ +package scaleway + +import ( + "context" + "github.com/external-secrets/external-secrets-e2e/framework" + "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/common" + esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" + esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" + "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sync" +) + +var cleanupOnce sync.Once + +var _ = ginkgo.Describe("[scaleway]", ginkgo.Label("scaleway"), func() { + + f := framework.New("eso-scaleway") + f.MakeRemoteRefKey = func(base string) string { + return "name:" + base + } + + // Initialization is deferred so that assertions work. + provider := &secretStoreProvider{} + + ginkgo.BeforeEach(func() { + + cfg, err := loadConfigFromEnv() + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + + provider.init(cfg) + + cleanupOnce.Do(provider.cleanup) + + createResources(context.Background(), f, cfg) + }) + + ginkgo.DescribeTable("sync secrets", framework.TableFunc(f, provider), + + //ginkgo.Entry(common.SyncV1Alpha1(f)), // not supported + ginkgo.Entry(common.SimpleDataSync(f)), + ginkgo.Entry(common.SyncWithoutTargetName(f)), + ginkgo.Entry(common.JSONDataWithProperty(f)), + ginkgo.Entry(common.JSONDataWithoutTargetName(f)), + ginkgo.Entry(common.JSONDataWithTemplate(f)), + ginkgo.Entry(common.JSONDataWithTemplateFromLiteral(f)), + ginkgo.Entry(common.TemplateFromConfigmaps(f)), + ginkgo.Entry(common.JSONDataFromSync(f)), + ginkgo.Entry(common.JSONDataFromRewrite(f)), + ginkgo.Entry(common.NestedJSONWithGJSON(f)), + ginkgo.Entry(common.DockerJSONConfig(f)), + ginkgo.Entry(common.DataPropertyDockerconfigJSON(f)), + ginkgo.Entry(common.SSHKeySync(f)), + ginkgo.Entry(common.SSHKeySyncDataProperty(f)), + ginkgo.Entry(common.DeletionPolicyDelete(f)), + //ginkgo.Entry(common.DecodingPolicySync(f)), // not supported + + ginkgo.Entry(common.FindByName(f)), + ginkgo.Entry(common.FindByNameAndRewrite(f)), + //ginkgo.Entry(common.FindByNameWithPath(f)), // not supported + + ginkgo.Entry(common.FindByTag(f)), + //ginkgo.Entry(common.FindByTagWithPath(f)), // not supported + ) +}) + +func createResources(ctx context.Context, f *framework.Framework, cfg *config) { + + apiKeySecretName := "scw-api-key" + apiKeySecretKey := "secret-key" + + // Creating a secret to hold the API key. + + secretSpec := v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: apiKeySecretName, + Namespace: f.Namespace.Name, + }, + StringData: map[string]string{ + "secret-key": cfg.secretKey, + }, + } + + err := f.CRClient.Create(ctx, &secretSpec) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + + // Creating SecretStore. + + secretStoreSpec := esv1beta1.SecretStore{ + ObjectMeta: metav1.ObjectMeta{ + Name: f.Namespace.Name, + Namespace: f.Namespace.Name, + }, + Spec: esv1beta1.SecretStoreSpec{ + Provider: &esv1beta1.SecretStoreProvider{ + Scaleway: &esv1beta1.ScalewayProvider{ + Region: cfg.region, + ProjectID: cfg.projectId, + AccessKey: &esv1beta1.ScalewayProviderSecretRef{ + Value: cfg.accessKey, // TODO: test with secretRef as well + }, + SecretKey: &esv1beta1.ScalewayProviderSecretRef{ + SecretRef: &esmeta.SecretKeySelector{ + Name: apiKeySecretName, + Key: apiKeySecretKey, + }, + }, + }, + }, + }, + } + + if cfg.apiUrl != nil { + secretStoreSpec.Spec.Provider.Scaleway.APIURL = *cfg.apiUrl + } + + err = f.CRClient.Create(ctx, &secretStoreSpec) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) +} diff --git a/go.mod b/go.mod index eaf8fc91771..7825c1c3cd6 100644 --- a/go.mod +++ b/go.mod @@ -68,6 +68,7 @@ require ( github.com/hashicorp/golang-lru v0.5.4 github.com/keeper-security/secrets-manager-go/core v1.5.0 github.com/maxbrunsfeld/counterfeiter/v6 v6.6.1 + github.com/scaleway/scaleway-sdk-go v1.0.0-beta.13.0.20230227165516-144b3e06ecf2 github.com/sethvargo/go-password v0.2.0 github.com/spf13/pflag v1.0.5 sigs.k8s.io/yaml v1.3.0 diff --git a/go.sum b/go.sum index a2b35b343ef..fbe7d1795ab 100644 --- a/go.sum +++ b/go.sum @@ -157,7 +157,7 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= -github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= +github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE= github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= @@ -507,6 +507,8 @@ github.com/rwtodd/Go.Sed v0.0.0-20210816025313-55464686f9ef/go.mod h1:8AEUvGVi2u github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.13.0.20230227165516-144b3e06ecf2 h1:LyHBuaec79FY+tmMHUdnctd/es78NzZ7VKcE2QmdPTc= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.13.0.20230227165516-144b3e06ecf2/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= github.com/sethvargo/go-password v0.2.0 h1:BTDl4CC/gjf/axHMaDQtw507ogrXLci6XRiLc7i/UHI= github.com/sethvargo/go-password v0.2.0/go.mod h1:Ym4Mr9JXLBycr02MFuVQ/0JHidNetSgbzutTr3zsYXE= diff --git a/hack/api-docs/mkdocs.yml b/hack/api-docs/mkdocs.yml index 5a0d0c01e84..aa7ab971f5e 100644 --- a/hack/api-docs/mkdocs.yml +++ b/hack/api-docs/mkdocs.yml @@ -98,6 +98,7 @@ nav: - senhasegura DevOps Secrets Management (DSM): provider/senhasegura-dsm.md - Doppler: provider/doppler.md - Keeper Security: provider/keeper-security.md + - Scaleway: provider/scaleway.md - Examples: - FluxCD: examples/gitops-using-fluxcd.md - Anchore Engine: examples/anchore-engine-credentials.md diff --git a/pkg/generator/register/register.go b/pkg/generator/register/register.go index 6c8d7a4226f..8d815a8af24 100644 --- a/pkg/generator/register/register.go +++ b/pkg/generator/register/register.go @@ -16,6 +16,7 @@ limitations under the License. package register // packages imported here are registered to the controller schema. + import ( _ "github.com/external-secrets/external-secrets/pkg/generator/acr" _ "github.com/external-secrets/external-secrets/pkg/generator/ecr" diff --git a/pkg/provider/register/register.go b/pkg/provider/register/register.go index cdd279de7b3..458e2cc716f 100644 --- a/pkg/provider/register/register.go +++ b/pkg/provider/register/register.go @@ -16,6 +16,7 @@ limitations under the License. package register // packages imported here are registered to the controller schema. + import ( _ "github.com/external-secrets/external-secrets/pkg/provider/akeyless" _ "github.com/external-secrets/external-secrets/pkg/provider/alibaba" @@ -30,6 +31,7 @@ import ( _ "github.com/external-secrets/external-secrets/pkg/provider/kubernetes" _ "github.com/external-secrets/external-secrets/pkg/provider/onepassword" _ "github.com/external-secrets/external-secrets/pkg/provider/oracle" + _ "github.com/external-secrets/external-secrets/pkg/provider/scaleway" _ "github.com/external-secrets/external-secrets/pkg/provider/senhasegura" _ "github.com/external-secrets/external-secrets/pkg/provider/vault" _ "github.com/external-secrets/external-secrets/pkg/provider/webhook" diff --git a/pkg/provider/scaleway/cache.go b/pkg/provider/scaleway/cache.go new file mode 100644 index 00000000000..a82ebb34b05 --- /dev/null +++ b/pkg/provider/scaleway/cache.go @@ -0,0 +1,97 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package scaleway + +import ( + "container/list" + "fmt" + "sync" +) + +// cache is for caching values of the secrets. Secret versions are immutable, thus there is no need +// for time-based expiration. +type cache interface { + Get(secretID string, revision uint32) ([]byte, bool) + Put(secretID string, revision uint32, value []byte) +} + +type cacheEntry struct { + value []byte + elem *list.Element +} + +type cacheImpl struct { + mutex sync.Mutex + entries map[string]cacheEntry + entryKeysByLastUsage list.List + maxEntryCount int +} + +func newCache() cache { + return &cacheImpl{ + entries: map[string]cacheEntry{}, + maxEntryCount: 500, + } +} + +func (c *cacheImpl) Get(secretID string, revision uint32) ([]byte, bool) { + c.mutex.Lock() + defer c.mutex.Unlock() + + key := c.key(secretID, revision) + + entry, ok := c.entries[key] + if !ok { + return nil, false + } + + c.entryKeysByLastUsage.MoveToFront(entry.elem) + + return entry.value, true +} + +func (c *cacheImpl) Put(secretID string, revision uint32, value []byte) { + c.mutex.Lock() + defer c.mutex.Unlock() + + key := c.key(secretID, revision) + + _, alreadyPresent := c.entries[key] + if alreadyPresent { + return + } + + if len(c.entries) == c.maxEntryCount { + c.evictLeastRecentlyUsed() + } + + entry := c.entryKeysByLastUsage.PushFront(key) + + c.entries[key] = cacheEntry{ + value: value, + elem: entry, + } +} + +func (c *cacheImpl) evictLeastRecentlyUsed() { + elem := c.entryKeysByLastUsage.Back() + + delete(c.entries, elem.Value.(string)) + + c.entryKeysByLastUsage.Remove(elem) +} + +func (c *cacheImpl) key(secretID string, revision uint32) string { + return fmt.Sprintf("%s/%d", secretID, revision) +} diff --git a/pkg/provider/scaleway/cache_test.go b/pkg/provider/scaleway/cache_test.go new file mode 100644 index 00000000000..6e5bc54888a --- /dev/null +++ b/pkg/provider/scaleway/cache_test.go @@ -0,0 +1,63 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package scaleway + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCacheMissReturnsFalse(t *testing.T) { + cache := newCache() + + _, ok := cache.Get("26f72b22-bcae-4131-a26e-b98abb3fa3dd", 1) + + assert.False(t, ok) +} + +func TestCachePutThenGet(t *testing.T) { + cache := newCache() + secretID := "cfd5dda5-dedb-40eb-b9c4-b9cf8e254727" + revision := uint32(1) + expectedValue := []byte("some value") + + cache.Put(secretID, revision, expectedValue) + + value, ok := cache.Get(secretID, revision) + assert.True(t, ok) + assert.Equal(t, expectedValue, value) +} + +func TestCacheLeastRecentlyUsedIsRemovedFirst(t *testing.T) { + cache := newCache() + secretID := "0c82ecf4-d3f7-4960-8301-0def5230eee2" + maxEntryCount := 500 + + for i := 0; i < maxEntryCount; i++ { + cache.Put(secretID, uint32(i+1), []byte{}) + } + + for i := 0; i < maxEntryCount; i++ { + cache.Get(secretID, uint32(i+1)) + } + + cache.Put(secretID, uint32(maxEntryCount+2), []byte{}) + + _, ok := cache.Get(secretID, 1) + assert.False(t, ok) + + _, ok = cache.Get(secretID, uint32(maxEntryCount+2)) + assert.True(t, ok) +} diff --git a/pkg/provider/scaleway/client.go b/pkg/provider/scaleway/client.go new file mode 100644 index 00000000000..2a69a143ca3 --- /dev/null +++ b/pkg/provider/scaleway/client.go @@ -0,0 +1,444 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package scaleway + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "strconv" + "strings" + "time" + + smapi "github.com/scaleway/scaleway-sdk-go/api/secret/v1alpha1" + "github.com/scaleway/scaleway-sdk-go/scw" + "github.com/tidwall/gjson" + + esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" + "github.com/external-secrets/external-secrets/pkg/find" +) + +var errNoSecretForName = errors.New("no secret for this name") + +type client struct { + api secretAPI + projectID string + cache cache +} + +const ( + refTypeName = "name" + refTypeID = "id" +) + +type scwSecretRef struct { + RefType string + Value string +} + +func (r scwSecretRef) String() string { + return fmt.Sprintf("%s:%s", r.RefType, r.Value) +} + +func decodeScwSecretRef(key string) (*scwSecretRef, error) { + sepIndex := strings.IndexRune(key, ':') + if sepIndex < 0 { + return nil, fmt.Errorf("invalid secret reference: missing colon ':'") + } + + return &scwSecretRef{ + RefType: key[:sepIndex], + Value: key[sepIndex+1:], + }, nil +} + +func (c *client) getSecretByName(ctx context.Context, name string) (*smapi.Secret, error) { + request := smapi.GetSecretByNameRequest{ + SecretName: name, + } + + response, err := c.api.GetSecretByName(&request, scw.WithContext(ctx)) + if err != nil { + //nolint:errorlint + if _, isErrNotFound := err.(*scw.ResourceNotFoundError); isErrNotFound { + return nil, errNoSecretForName + } + return nil, err + } + + return response, nil +} + +func (c *client) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) { + scwRef, err := decodeScwSecretRef(ref.Key) + if err != nil { + return nil, err + } + + versionSpec := "latest_enabled" + if ref.Version != "" { + versionSpec = ref.Version + } + + value, err := c.accessSecretVersion(ctx, scwRef, versionSpec) + if err != nil { + //nolint:errorlint + if _, isNotFoundErr := err.(*scw.ResourceNotFoundError); isNotFoundErr { + return nil, esv1beta1.NoSecretError{} + } + return nil, err + } + + if ref.Property != "" { + extracted, err := extractJSONProperty(value, ref.Property) + if err != nil { + return nil, err + } + + value = extracted + } + + return value, nil +} + +func (c *client) PushSecret(ctx context.Context, value []byte, remoteRef esv1beta1.PushRemoteRef) error { + scwRef, err := decodeScwSecretRef(remoteRef.GetRemoteKey()) + if err != nil { + return err + } + + if scwRef.RefType != refTypeName { + return fmt.Errorf("secrets can only be pushed by name") + } + secretName := scwRef.Value + + // First, we do a GetSecretVersion() to resolve the secret id and the last revision number. + + var secretID string + secretExists := false + existingSecretVersion := int64(-1) + + secretVersion, err := c.api.GetSecretVersionByName(&smapi.GetSecretVersionByNameRequest{ + SecretName: secretName, + Revision: "latest", + }, scw.WithContext(ctx)) + if err != nil { + //nolint:errorlint + if notFoundErr, ok := err.(*scw.ResourceNotFoundError); ok { + if notFoundErr.Resource == "secret_version" { + secretExists = true + } + } else { + return err + } + } else { + secretExists = true + existingSecretVersion = int64(secretVersion.Revision) + } + + if secretExists { + if existingSecretVersion != -1 { + // If the secret exists, we can fetch its last value to see if we have any change to make. + + secretID = secretVersion.SecretID + + data, err := c.accessSpecificSecretVersion(ctx, secretID, secretVersion.Revision) + if err != nil { + return err + } + + if bytes.Equal(data, value) { + // No change to push. + return nil + } + } else { + // If the secret exists but has no versions, we need an additional GetSecret() to resolve the secret id. + // This may happen if a push was interrupted. + + secret, err := c.api.GetSecretByName(&smapi.GetSecretByNameRequest{ + SecretName: secretName, + }, scw.WithContext(ctx)) + if err != nil { + return err + } + + secretID = secret.ID + } + } else { + // If the secret does not exist, we need to create it. + + secret, err := c.api.CreateSecret(&smapi.CreateSecretRequest{ + ProjectID: c.projectID, + Name: secretName, + }, scw.WithContext(ctx)) + if err != nil { + return err + } + + secretID = secret.ID + } + + // Finally, we push the new secret version. + + createSecretVersionRequest := smapi.CreateSecretVersionRequest{ + SecretID: secretID, + Data: value, + } + + createSecretVersionResponse, err := c.api.CreateSecretVersion(&createSecretVersionRequest, scw.WithContext(ctx)) + if err != nil { + return err + } + + c.cache.Put(secretID, createSecretVersionResponse.Revision, value) + + if secretExists && existingSecretVersion != -1 { + _, err := c.api.DisableSecretVersion(&smapi.DisableSecretVersionRequest{ + SecretID: secretID, + Revision: fmt.Sprintf("%d", existingSecretVersion), + }) + if err != nil { + return err + } + } + + return nil +} + +func (c *client) DeleteSecret(ctx context.Context, remoteRef esv1beta1.PushRemoteRef) error { + scwRef, err := decodeScwSecretRef(remoteRef.GetRemoteKey()) + if err != nil { + return err + } + + if scwRef.RefType != refTypeName { + return fmt.Errorf("secrets can only be pushed by name") + } + secretName := scwRef.Value + + secret, err := c.getSecretByName(ctx, secretName) + if err != nil { + if errors.Is(err, errNoSecretForName) { + return nil + } + return err + } + + request := smapi.DeleteSecretRequest{ + SecretID: secret.ID, + } + + err = c.api.DeleteSecret(&request, scw.WithContext(ctx)) + if err != nil { + return err + } + + return nil +} + +func (c *client) Validate() (esv1beta1.ValidationResult, error) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + page := int32(1) + pageSize := uint32(0) + _, err := c.api.ListSecrets(&smapi.ListSecretsRequest{ + ProjectID: &c.projectID, + Page: &page, + PageSize: &pageSize, + }, scw.WithContext(ctx)) + if err != nil { + return esv1beta1.ValidationResultError, nil + } + + return esv1beta1.ValidationResultReady, nil +} + +func (c *client) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) { + rawData, err := c.GetSecret(ctx, ref) + if err != nil { + return nil, err + } + + structuredData := make(map[string]json.RawMessage) + + err = json.Unmarshal(rawData, &structuredData) + if err != nil { + return nil, err + } + + values := make(map[string][]byte) + + for key, value := range structuredData { + values[key] = jsonToSecretData(value) + } + + return values, nil +} + +// GetAllSecrets lists secrets matching the given criteria and return their latest versions. +func (c *client) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) { + request := smapi.ListSecretsRequest{ + ProjectID: &c.projectID, + Page: new(int32), + PageSize: new(uint32), + } + *request.Page = 1 + *request.PageSize = 50 + + if ref.Path != nil { + return nil, fmt.Errorf("searching by path is not supported") + } + + var nameMatcher *find.Matcher + if ref.Name != nil { + var err error + nameMatcher, err = find.New(*ref.Name) + if err != nil { + return nil, err + } + } + + for tag := range ref.Tags { + request.Tags = append(request.Tags, tag) + } + + results := map[string][]byte{} + + for done := false; !done; { + response, err := c.api.ListSecrets(&request, scw.WithContext(ctx)) + if err != nil { + return nil, err + } + + totalFetched := uint64(*request.Page-1)*uint64(*request.PageSize) + uint64(len(response.Secrets)) + done = totalFetched == uint64(response.TotalCount) + + *request.Page++ + + for _, secret := range response.Secrets { + if nameMatcher != nil && !nameMatcher.MatchName(secret.Name) { + continue + } + + accessReq := smapi.AccessSecretVersionRequest{ + Region: secret.Region, + SecretID: secret.ID, + Revision: "latest_enabled", + } + + accessResp, err := c.api.AccessSecretVersion(&accessReq, scw.WithContext(ctx)) + if err != nil { + log.Error(err, "failed to access secret") + continue + } + + results[secret.Name] = accessResp.Data + } + } + + return results, nil +} + +func (c *client) Close(context.Context) error { + return nil +} + +func (c *client) accessSecretVersion(ctx context.Context, secretRef *scwSecretRef, versionSpec string) ([]byte, error) { + // if we have a secret id and a revision number, we can avoid an extra GetSecret() + + if secretRef.RefType == refTypeID && len(versionSpec) > 0 && '0' <= versionSpec[0] && versionSpec[0] <= '9' { + secretID := secretRef.Value + + revision, err := strconv.ParseUint(versionSpec, 10, 32) + if err == nil { + return c.accessSpecificSecretVersion(ctx, secretID, uint32(revision)) + } + } + + // otherwise, we do a GetSecret() first to avoid transferring the secret value if it is cached + + var secretID string + var secretRevision uint32 + + switch secretRef.RefType { + case refTypeID: + request := smapi.GetSecretVersionRequest{ + SecretID: secretRef.Value, + Revision: versionSpec, + } + response, err := c.api.GetSecretVersion(&request, scw.WithContext(ctx)) + if err != nil { + return nil, err + } + secretID = response.SecretID + secretRevision = response.Revision + case refTypeName: + request := smapi.GetSecretVersionByNameRequest{ + SecretName: secretRef.Value, + Revision: versionSpec, + } + response, err := c.api.GetSecretVersionByName(&request, scw.WithContext(ctx)) + if err != nil { + return nil, err + } + secretID = response.SecretID + secretRevision = response.Revision + default: + return nil, fmt.Errorf("invalid secret reference: %q", secretRef.Value) + } + + return c.accessSpecificSecretVersion(ctx, secretID, secretRevision) +} + +func (c *client) accessSpecificSecretVersion(ctx context.Context, secretID string, revision uint32) ([]byte, error) { + cachedValue, cacheHit := c.cache.Get(secretID, revision) + if cacheHit { + return cachedValue, nil + } + + request := smapi.AccessSecretVersionRequest{ + SecretID: secretID, + Revision: fmt.Sprintf("%d", revision), + } + + response, err := c.api.AccessSecretVersion(&request, scw.WithContext(ctx)) + if err != nil { + return nil, err + } + + return response.Data, nil +} + +func jsonToSecretData(value json.RawMessage) []byte { + var stringValue string + err := json.Unmarshal(value, &stringValue) + if err == nil { + return []byte(stringValue) + } + + return []byte(strings.TrimSpace(string(value))) +} + +func extractJSONProperty(secretData []byte, property string) ([]byte, error) { + result := gjson.Get(string(secretData), property) + + if !result.Exists() { + return nil, esv1beta1.NoSecretError{} + } + + return jsonToSecretData(json.RawMessage(result.Raw)), nil +} diff --git a/pkg/provider/scaleway/client_test.go b/pkg/provider/scaleway/client_test.go new file mode 100644 index 00000000000..54e53c649ea --- /dev/null +++ b/pkg/provider/scaleway/client_test.go @@ -0,0 +1,386 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package scaleway + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + + esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" +) + +var db = buildDB(&fakeSecretAPI{ + secrets: []*fakeSecret{ + { + name: "secret-1", + versions: []*fakeSecretVersion{ + {revision: 1}, + {revision: 2}, + {revision: 3, status: "disabled"}, + }, + }, + { + name: "secret-2", + tags: []string{"secret-2-tag-1", "secret-2-tag-2"}, + versions: []*fakeSecretVersion{ + {revision: 1}, + {revision: 2}, + }, + }, + { + name: "push-me", + versions: []*fakeSecretVersion{}, + }, + { + name: "not-changed", + versions: []*fakeSecretVersion{ + {revision: 1}, + }, + }, + { + name: "disabling-old-versions", + versions: []*fakeSecretVersion{ + {revision: 1}, + }, + }, + { + name: "json-data", + versions: []*fakeSecretVersion{ + { + revision: 1, + data: []byte(`{"some_string": "abc def", "some_int": -100, "some_bool": false}`), + }, + }, + }, + { + name: "cant-push", + versions: []*fakeSecretVersion{ + {revision: 1}, + }, + }, + { + name: "json-nested", + versions: []*fakeSecretVersion{ + {revision: 1, data: []byte( + `{"root":{"intermediate":{"leaf":9}}}`, + )}, + }, + }, + }, +}) + +func newTestClient() esv1beta1.SecretsClient { + return &client{ + api: db, + cache: newCache(), + } +} + +func TestGetSecret(t *testing.T) { + ctx := context.Background() + c := newTestClient() + + secret := db.secrets[0] + + testCases := map[string]struct { + ref esv1beta1.ExternalSecretDataRemoteRef + response []byte + err error + }{ + "empty version should mean latest_enabled": { + ref: esv1beta1.ExternalSecretDataRemoteRef{ + Key: "id:" + secret.id, + Version: "", + }, + response: secret.versions[1].data, + }, + "asking for latest version": { + ref: esv1beta1.ExternalSecretDataRemoteRef{ + Key: "id:" + secret.id, + Version: "latest", + }, + response: secret.versions[2].data, + }, + "asking for latest version by name": { + ref: esv1beta1.ExternalSecretDataRemoteRef{ + Key: "name:" + secret.name, + Version: "latest", + }, + response: secret.versions[2].data, + }, + "asking for version by revision number": { + ref: esv1beta1.ExternalSecretDataRemoteRef{ + Key: "id:" + secret.id, + Version: "1", + }, + response: secret.versions[0].data, + }, + "asking for version by revision number and name": { + ref: esv1beta1.ExternalSecretDataRemoteRef{ + Key: "name:" + secret.name, + Version: "1", + }, + response: secret.versions[0].data, + }, + "asking for nested json property": { + ref: esv1beta1.ExternalSecretDataRemoteRef{ + Key: "id:" + db.secret("json-nested").id, + Property: "root.intermediate.leaf", + Version: "latest", + }, + response: []byte("9"), + }, + "non existing secret id should yield NoSecretErr": { + ref: esv1beta1.ExternalSecretDataRemoteRef{ + Key: "id:730aa98d-ec0c-4426-8202-b11aeec8ea1e", + }, + err: esv1beta1.NoSecretErr, + }, + "non existing secret name should yield NoSecretErr": { + ref: esv1beta1.ExternalSecretDataRemoteRef{ + Key: "name:not-a-secret", + }, + err: esv1beta1.NoSecretErr, + }, + "non existing revision should yield NoSecretErr": { + ref: esv1beta1.ExternalSecretDataRemoteRef{ + Key: "id:" + secret.id, + Version: "9999", + }, + err: esv1beta1.NoSecretErr, + }, + "non existing json property should yield not found": { + ref: esv1beta1.ExternalSecretDataRemoteRef{ + Key: "id:" + db.secret("json-nested").id, + Property: "root.intermediate.missing", + Version: "latest", + }, + err: esv1beta1.NoSecretErr, + }, + } + + for tcName, tc := range testCases { + t.Run(tcName, func(t *testing.T) { + response, err := c.GetSecret(ctx, tc.ref) + if tc.err == nil { + assert.NoError(t, err) + assert.Equal(t, tc.response, response) + } else { + assert.Nil(t, response) + assert.ErrorIs(t, err, tc.err) + assert.Equal(t, tc.err, err) + } + }) + } +} + +type pushRemoteRef string + +func (ref pushRemoteRef) GetRemoteKey() string { + return string(ref) +} + +func TestPushSecret(t *testing.T) { + t.Run("to new secret", func(t *testing.T) { + ctx := context.Background() + c := newTestClient() + data := []byte("some secret data 6a8ff33b-c69a-4e42-b162-b7b595ee7f5f") + secretName := "secret-creation-test" + + pushErr := c.PushSecret(ctx, data, pushRemoteRef("name:"+secretName)) + + assert.NoError(t, pushErr) + assert.Len(t, db.secret(secretName).versions, 1) + assert.Equal(t, data, db.secret(secretName).versions[0].data) + }) + + t.Run("to secret created by us", func(t *testing.T) { + ctx := context.Background() + c := newTestClient() + data := []byte("some secret data a11d416b-9169-4f4a-8c27-d2959b22e189") + secretName := "secret-update-test" + assert.NoError(t, c.PushSecret(ctx, []byte("original data"), pushRemoteRef("name:"+secretName))) + + pushErr := c.PushSecret(ctx, data, pushRemoteRef("name:"+secretName)) + + assert.NoError(t, pushErr) + assert.Len(t, db.secret(secretName).versions, 2) + assert.Equal(t, data, db.secret(secretName).versions[1].data) + }) + + t.Run("to secret partially created by us with no version", func(t *testing.T) { + ctx := context.Background() + c := newTestClient() + data := []byte("some secret data a11d416b-9169-4f4a-8c27-d2959b22e189") + secretName := "push-me" + + pushErr := c.PushSecret(ctx, data, pushRemoteRef("name:"+secretName)) + + assert.NoError(t, pushErr) + assert.Len(t, db.secret(secretName).versions, 1) + assert.Equal(t, data, db.secret(secretName).versions[0].data) + }) + + t.Run("by invalid secret ref is an error", func(t *testing.T) { + ctx := context.Background() + c := newTestClient() + + pushErr := c.PushSecret(ctx, []byte("some data"), pushRemoteRef("invalid:abcd")) + + assert.Error(t, pushErr) + }) + + t.Run("by id is an error", func(t *testing.T) { + ctx := context.Background() + c := newTestClient() + + pushErr := c.PushSecret(ctx, []byte("some data"), pushRemoteRef("id:"+db.secret("cant-push").id)) + + assert.Error(t, pushErr) + }) + + t.Run("without change does not create a version", func(t *testing.T) { + ctx := context.Background() + c := newTestClient() + secret := db.secret("not-changed") + + pushErr := c.PushSecret(ctx, secret.versions[0].data, pushRemoteRef("name:"+secret.name)) + + assert.NoError(t, pushErr) + assert.Equal(t, 1, len(secret.versions)) + }) + + t.Run("previous version is disabled", func(t *testing.T) { + ctx := context.Background() + c := newTestClient() + secret := db.secret("disabling-old-versions") + + pushErr := c.PushSecret(ctx, []byte("some new data"), pushRemoteRef("name:"+secret.name)) + + assert.NoError(t, pushErr) + assert.Equal(t, 2, len(secret.versions)) + assert.Equal(t, "disabled", secret.versions[0].status) + }) +} + +func TestGetSecretMap(t *testing.T) { + ctx := context.Background() + c := newTestClient() + + values, getErr := c.GetSecretMap(ctx, esv1beta1.ExternalSecretDataRemoteRef{ + Key: "id:" + db.secret("json-data").id, + Version: "latest", + }) + + assert.NoError(t, getErr) + assert.Equal(t, map[string][]byte{ + "some_string": []byte("abc def"), + "some_int": []byte("-100"), + "some_bool": []byte("false"), + }, values) +} + +func TestGetSecretMapNested(t *testing.T) { + ctx := context.Background() + c := newTestClient() + + values, getErr := c.GetSecretMap(ctx, esv1beta1.ExternalSecretDataRemoteRef{ + Key: "id:" + db.secret("json-nested").id, + Property: "root.intermediate", + Version: "latest", + }) + + assert.NoError(t, getErr) + assert.Equal(t, map[string][]byte{ + "leaf": []byte("9"), + }, values) +} + +func TestGetAllSecrets(t *testing.T) { + ctx := context.Background() + c := newTestClient() + + testCases := map[string]struct { + ref esv1beta1.ExternalSecretFind + response map[string][]byte + err error + }{ + "find secrets by name": { + ref: esv1beta1.ExternalSecretFind{ + Name: &esv1beta1.FindName{RegExp: "secret-.*"}, + }, + response: map[string][]byte{ + db.secret("secret-1").name: db.secret("secret-1").mustGetVersion("latest_enabled").data, + db.secret("secret-2").name: db.secret("secret-2").mustGetVersion("latest_enabled").data, + }, + }, + "find secrets by tags": { + ref: esv1beta1.ExternalSecretFind{ + Tags: map[string]string{"secret-2-tag-1": "ignored-value"}, + }, + response: map[string][]byte{ + db.secrets[1].name: db.secrets[1].mustGetVersion("latest").data, + }, + }, + } + + for tcName, tc := range testCases { + t.Run(tcName, func(t *testing.T) { + response, err := c.GetAllSecrets(ctx, tc.ref) + if tc.err == nil { + assert.NoError(t, err) + assert.Equal(t, tc.response, response) + } else { + assert.Nil(t, response) + assert.ErrorIs(t, err, tc.err) + assert.Equal(t, tc.err, err) + } + }) + } +} + +func TestDeleteSecret(t *testing.T) { + ctx := context.Background() + c := newTestClient() + + secret := db.secrets[0] + + testCases := map[string]struct { + ref esv1beta1.PushRemoteRef + err error + }{ + "Delete Successfully": { + ref: pushRemoteRef("name:" + secret.name), + err: nil, + }, + "Secret Not Found": { + ref: pushRemoteRef("name:not-a-secret"), + err: nil, + }, + } + + for tcName, tc := range testCases { + t.Run(tcName, func(t *testing.T) { + err := c.DeleteSecret(ctx, tc.ref) + if tc.err == nil { + assert.NoError(t, err) + } else { + assert.ErrorIs(t, err, tc.err) + assert.Equal(t, tc.err, err) + } + }) + } +} diff --git a/pkg/provider/scaleway/fake_secret_api_test.go b/pkg/provider/scaleway/fake_secret_api_test.go new file mode 100644 index 00000000000..dd345cac953 --- /dev/null +++ b/pkg/provider/scaleway/fake_secret_api_test.go @@ -0,0 +1,441 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package scaleway + +import ( + "fmt" + "sort" + "strconv" + + "github.com/google/uuid" + smapi "github.com/scaleway/scaleway-sdk-go/api/secret/v1alpha1" + "github.com/scaleway/scaleway-sdk-go/scw" +) + +type fakeSecretVersion struct { + revision int + data []byte + dontFillData bool + status string +} + +type fakeSecret struct { + id string + name string + versions []*fakeSecretVersion + tags []string + status string +} + +type fakeSecretAPI struct { + secrets []*fakeSecret + _secretsByID map[string]*fakeSecret + _secretsByName map[string]*fakeSecret +} + +func buildDB(f *fakeSecretAPI) *fakeSecretAPI { + f._secretsByID = map[string]*fakeSecret{} + f._secretsByName = map[string]*fakeSecret{} + + for _, secret := range f.secrets { + if secret.id == "" { + secret.id = uuid.NewString() + } + + sort.Slice(secret.versions, func(i, j int) bool { + return secret.versions[i].revision < secret.versions[j].revision + }) + + for index, version := range secret.versions { + if version.revision != index+1 { + panic("bad revision number in fixtures") + } + + if version.status == "" { + version.status = "enabled" + } + } + + for _, version := range secret.versions { + if len(version.data) == 0 && !version.dontFillData { + version.data = []byte(fmt.Sprintf("some data for secret %s version %d: %s", secret.id, version.revision, uuid.NewString())) + } + } + + if secret.status == "" { + secret.status = "ready" + } + + f._secretsByID[secret.id] = secret + f._secretsByName[secret.name] = secret + } + + return f +} + +func (s *fakeSecret) getVersion(revision string) (*fakeSecretVersion, bool) { + if len(s.versions) == 0 { + return nil, false + } + + if revision == "latest" { + return s.versions[len(s.versions)-1], true + } + + if revision == "latest_enabled" { + for i := len(s.versions) - 1; i >= 0; i-- { + if s.versions[i].status == "enabled" { + return s.versions[i], true + } + } + return nil, false + } + + revisionNumber, err := strconv.Atoi(revision) + if err != nil { + return nil, false + } + + i, found := sort.Find(len(s.versions), func(i int) int { + if revisionNumber < s.versions[i].revision { + return -1 + } else if revisionNumber > s.versions[i].revision { + return 1 + } else { + return 0 + } + }) + if found { + return s.versions[i], true + } + return nil, false +} + +func (s *fakeSecret) mustGetVersion(revision string) *fakeSecretVersion { + version, ok := s.getVersion(revision) + if !ok { + panic("no such version") + } + + return version +} + +func (f *fakeSecretAPI) secret(name string) *fakeSecret { + return f._secretsByName[name] +} + +func (f *fakeSecretAPI) getSecretByID(secretID string) (*fakeSecret, error) { + secret, foundSecret := f._secretsByID[secretID] + + if !foundSecret { + return nil, &scw.ResourceNotFoundError{ + Resource: "secret", + ResourceID: secretID, + } + } + + return secret, nil +} + +func (f *fakeSecretAPI) getSecretByName(secretName string) (*fakeSecret, error) { + secret, foundSecret := f._secretsByName[secretName] + + if !foundSecret { + return nil, &scw.ResourceNotFoundError{ + Resource: "secret", + ResourceID: secretName, + } + } + + return secret, nil +} + +func (f *fakeSecretAPI) GetSecret(request *smapi.GetSecretRequest, _ ...scw.RequestOption) (*smapi.Secret, error) { + if request.Region != "" { + panic("explicit region in request is not supported") + } + + secret, err := f.getSecretByID(request.SecretID) + if err != nil { + return nil, err + } + + return &smapi.Secret{ + ID: secret.id, + Name: secret.name, + Status: smapi.SecretStatus(secret.status), + Tags: secret.tags, + VersionCount: uint32(len(secret.versions)), + }, nil +} + +func (f *fakeSecretAPI) GetSecretByName(request *smapi.GetSecretByNameRequest, _ ...scw.RequestOption) (*smapi.Secret, error) { + if request.Region != "" { + panic("explicit region in request is not supported") + } + + secret, err := f.getSecretByName(request.SecretName) + if err != nil { + return nil, err + } + + return &smapi.Secret{ + ID: secret.id, + Name: secret.name, + Status: smapi.SecretStatus(secret.status), + Tags: secret.tags, + VersionCount: uint32(len(secret.versions)), + }, nil +} + +func (f *fakeSecretAPI) GetSecretVersion(request *smapi.GetSecretVersionRequest, _ ...scw.RequestOption) (*smapi.SecretVersion, error) { + if request.Region != "" { + panic("explicit region in request is not supported") + } + + secret, err := f.getSecretByID(request.SecretID) + if err != nil { + return nil, err + } + + version, ok := secret.getVersion(request.Revision) + if !ok { + return nil, &scw.ResourceNotFoundError{ + Resource: "secret_version", + ResourceID: request.Revision, + } + } + + return &smapi.SecretVersion{ + SecretID: secret.id, + Revision: uint32(version.revision), + Status: smapi.SecretVersionStatus(secret.status), + }, nil +} + +func (f *fakeSecretAPI) GetSecretVersionByName(request *smapi.GetSecretVersionByNameRequest, _ ...scw.RequestOption) (*smapi.SecretVersion, error) { + if request.Region != "" { + panic("explicit region in request is not supported") + } + + secret, err := f.getSecretByName(request.SecretName) + if err != nil { + return nil, err + } + + version, ok := secret.getVersion(request.Revision) + if !ok { + return nil, &scw.ResourceNotFoundError{ + Resource: "secret_version", + ResourceID: request.Revision, + } + } + + return &smapi.SecretVersion{ + SecretID: secret.id, + Revision: uint32(version.revision), + Status: smapi.SecretVersionStatus(secret.status), + }, nil +} + +func (f *fakeSecretAPI) AccessSecretVersion(request *smapi.AccessSecretVersionRequest, _ ...scw.RequestOption) (*smapi.AccessSecretVersionResponse, error) { + if request.Region != "" { + panic("explicit region in request is not supported") + } + + secret, err := f.getSecretByID(request.SecretID) + if err != nil { + return nil, err + } + + version, ok := secret.getVersion(request.Revision) + if !ok { + return nil, &scw.ResourceNotFoundError{ + Resource: "secret_version", + ResourceID: request.Revision, + } + } + + return &smapi.AccessSecretVersionResponse{ + SecretID: secret.id, + Revision: uint32(version.revision), + Data: version.data, + }, nil +} + +func (f *fakeSecretAPI) DisableSecretVersion(request *smapi.DisableSecretVersionRequest, _ ...scw.RequestOption) (*smapi.SecretVersion, error) { + if request.Region != "" { + panic("explicit region in request is not supported") + } + + secret, err := f.getSecretByID(request.SecretID) + if err != nil { + return nil, err + } + + version, ok := secret.getVersion(request.Revision) + if !ok { + return nil, &scw.ResourceNotFoundError{ + Resource: "secret_version", + ResourceID: request.Revision, + } + } + + version.status = "disabled" + + return &smapi.SecretVersion{ + SecretID: secret.id, + Revision: uint32(version.revision), + Status: smapi.SecretVersionStatus(version.status), + }, nil +} + +func matchListSecretFilter(secret *fakeSecret, filter *smapi.ListSecretsRequest) bool { + for _, requiredTag := range filter.Tags { + found := false + + for _, secretTag := range secret.tags { + if requiredTag == secretTag { + found = true + break + } + } + + if !found { + return false + } + } + + return true +} + +func (f *fakeSecretAPI) ListSecrets(request *smapi.ListSecretsRequest, _ ...scw.RequestOption) (*smapi.ListSecretsResponse, error) { + var matches []*fakeSecret + + // filtering + + for _, secret := range f.secrets { + if matchListSecretFilter(secret, request) { + matches = append(matches, secret) + } + } + + // ordering + + if request.OrderBy != "" { + panic("explicit order by is not implemented") + } + + sort.Slice(matches, func(i, j int) bool { + return matches[i].id >= matches[j].id + }) + + // pagination + + response := smapi.ListSecretsResponse{ + TotalCount: uint32(len(matches)), + } + + if request.Page == nil || request.PageSize == nil { + panic("list secrets without explicit pagination not implemented") + } + page := int(*request.Page) + pageSize := int(*request.PageSize) + + startOffset := (page - 1) * pageSize + if startOffset > len(matches) { + return nil, fmt.Errorf("invalid page offset (page = %d, page size = %d, total = %d)", page, pageSize, len(matches)) + } + + endOffset := page * pageSize + if endOffset > len(matches) { + endOffset = len(matches) + } + + for _, secret := range matches[startOffset:endOffset] { + response.Secrets = append(response.Secrets, &smapi.Secret{ + ID: secret.id, + Name: secret.name, + Status: smapi.SecretStatus(secret.status), + Tags: secret.tags, + VersionCount: uint32(len(secret.versions)), + }) + } + + return &response, nil +} + +func (f *fakeSecretAPI) CreateSecret(request *smapi.CreateSecretRequest, _ ...scw.RequestOption) (*smapi.Secret, error) { + if request.Region != "" { + panic("explicit region in request is not supported") + } + + secret := &fakeSecret{ + id: uuid.NewString(), + name: request.Name, + status: "ready", + } + + f.secrets = append(f.secrets, secret) + f._secretsByID[secret.id] = secret + f._secretsByName[secret.name] = secret + + return &smapi.Secret{ + ID: secret.id, + ProjectID: request.ProjectID, + Name: secret.name, + Status: smapi.SecretStatus(secret.status), + VersionCount: 0, + }, nil +} + +func (f *fakeSecretAPI) CreateSecretVersion(request *smapi.CreateSecretVersionRequest, _ ...scw.RequestOption) (*smapi.SecretVersion, error) { + if request.Region != "" { + panic("explicit region in request is not supported") + } + + secret, ok := f._secretsByID[request.SecretID] + if !ok { + return nil, &scw.ResourceNotFoundError{ + Resource: "secret", + ResourceID: request.SecretID, + } + } + + newVersion := &fakeSecretVersion{ + revision: len(secret.versions) + 1, + data: request.Data, + } + + secret.versions = append(secret.versions, newVersion) + + return &smapi.SecretVersion{ + SecretID: request.SecretID, + Revision: uint32(newVersion.revision), + Status: smapi.SecretVersionStatus(newVersion.status), + }, nil +} + +func (f *fakeSecretAPI) DeleteSecret(request *smapi.DeleteSecretRequest, _ ...scw.RequestOption) error { + secret, ok := f._secretsByID[request.SecretID] + if !ok { + return &scw.ResourceNotFoundError{ + Resource: "secret", + ResourceID: request.SecretID, + } + } + delete(f._secretsByID, secret.id) + + return nil +} diff --git a/pkg/provider/scaleway/provider.go b/pkg/provider/scaleway/provider.go new file mode 100644 index 00000000000..a15dfc39ec6 --- /dev/null +++ b/pkg/provider/scaleway/provider.go @@ -0,0 +1,195 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package scaleway + +import ( + "context" + "fmt" + + smapi "github.com/scaleway/scaleway-sdk-go/api/secret/v1alpha1" + "github.com/scaleway/scaleway-sdk-go/scw" + "github.com/scaleway/scaleway-sdk-go/validation" + corev1 "k8s.io/api/core/v1" + ctrl "sigs.k8s.io/controller-runtime" + kubeClient "sigs.k8s.io/controller-runtime/pkg/client" + + esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" + "github.com/external-secrets/external-secrets/pkg/utils" +) + +var ( + defaultAPIURL = "https://api.scaleway.com" + log = ctrl.Log.WithName("provider").WithName("scaleway") +) + +type Provider struct{} + +// Capabilities return the provider supported capabilities (ReadOnly, WriteOnly, ReadWrite). +func (p *Provider) Capabilities() esv1beta1.SecretStoreCapabilities { + return esv1beta1.SecretStoreReadWrite +} + +func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore, kube kubeClient.Client, namespace string) (esv1beta1.SecretsClient, error) { + cfg, err := getConfig(store) + if err != nil { + return nil, err + } + + if store.GetKind() == esv1beta1.ClusterSecretStoreKind && doesConfigDependOnNamespace(cfg) { + // we are not attached to a specific namespace, but some config values are dependent on it + return nil, fmt.Errorf("when using a ClusterSecretStore, namespaces must be explicitly set") + } + + accessKey, err := loadConfigSecret(ctx, cfg.AccessKey, kube, namespace) + if err != nil { + return nil, err + } + + secretKey, err := loadConfigSecret(ctx, cfg.SecretKey, kube, namespace) + if err != nil { + return nil, err + } + + scwClient, err := scw.NewClient( + scw.WithAPIURL(cfg.APIURL), + scw.WithDefaultRegion(scw.Region(cfg.Region)), + scw.WithDefaultProjectID(cfg.ProjectID), + scw.WithAuth(accessKey, secretKey), + ) + if err != nil { + return nil, err + } + + return &client{ + api: smapi.NewAPI(scwClient), + projectID: cfg.ProjectID, + cache: newCache(), + }, nil +} + +func loadConfigSecret(ctx context.Context, ref *esv1beta1.ScalewayProviderSecretRef, kube kubeClient.Client, defaultNamespace string) (string, error) { + if ref.SecretRef == nil { + return ref.Value, nil + } + + namespace := defaultNamespace + if ref.SecretRef.Namespace != nil { + namespace = *ref.SecretRef.Namespace + } + + if ref.SecretRef.Name == "" { + return "", fmt.Errorf("must specify a value or a reference to a secret") + } + + if ref.SecretRef.Key == "" { + return "", fmt.Errorf("must specify a secret key") + } + + objKey := kubeClient.ObjectKey{ + Namespace: namespace, + Name: ref.SecretRef.Name, + } + + secret := corev1.Secret{} + + err := kube.Get(ctx, objKey, &secret) + if err != nil { + return "", err + } + + value, ok := secret.Data[ref.SecretRef.Key] + if !ok { + return "", fmt.Errorf("no such key in secret: %v", ref.SecretRef.Key) + } + + return string(value), nil +} + +func validateSecretRef(store esv1beta1.GenericStore, ref *esv1beta1.ScalewayProviderSecretRef) error { + if ref.SecretRef != nil { + if ref.Value != "" { + return fmt.Errorf("cannot specify both secret reference and value") + } + err := utils.ValidateReferentSecretSelector(store, *ref.SecretRef) + if err != nil { + return err + } + } else if ref.Value == "" { + return fmt.Errorf("must specify either secret reference or direct value") + } + + return nil +} + +func doesConfigDependOnNamespace(cfg *esv1beta1.ScalewayProvider) bool { + if cfg.AccessKey.SecretRef != nil && cfg.AccessKey.SecretRef.Namespace != nil { + return true + } + + if cfg.SecretKey.SecretRef != nil && cfg.SecretKey.SecretRef.Namespace != nil { + return true + } + + return false +} + +func getConfig(store esv1beta1.GenericStore) (*esv1beta1.ScalewayProvider, error) { + if store == nil { + return nil, fmt.Errorf("missing store specification") + } + storeSpec := store.GetSpec() + + if storeSpec == nil || storeSpec.Provider == nil || storeSpec.Provider.Scaleway == nil { + return nil, fmt.Errorf("invalid specification for scaleway provider") + } + cfg := storeSpec.Provider.Scaleway + + if cfg.APIURL == "" { + cfg.APIURL = defaultAPIURL + } else if !validation.IsURL(cfg.APIURL) { + return nil, fmt.Errorf("invalid api url: %q", cfg.APIURL) + } + + if !validation.IsRegion(cfg.Region) { + return nil, fmt.Errorf("invalid region: %q", cfg.Region) + } + + if !validation.IsProjectID(cfg.ProjectID) { + return nil, fmt.Errorf("invalid project id: %q", cfg.ProjectID) + } + + err := validateSecretRef(store, cfg.AccessKey) + if err != nil { + return nil, err + } + + err = validateSecretRef(store, cfg.SecretKey) + if err != nil { + return nil, err + } + + return cfg, nil +} + +func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error { + _, err := getConfig(store) + return err +} + +func init() { + esv1beta1.Register(&Provider{}, &esv1beta1.SecretStoreProvider{ + Scaleway: &esv1beta1.ScalewayProvider{}, + }) +} diff --git a/pkg/provider/scaleway/secret_api.go b/pkg/provider/scaleway/secret_api.go new file mode 100644 index 00000000000..06d68cdf8b5 --- /dev/null +++ b/pkg/provider/scaleway/secret_api.go @@ -0,0 +1,32 @@ +/* +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 implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package scaleway + +import ( + smapi "github.com/scaleway/scaleway-sdk-go/api/secret/v1alpha1" + "github.com/scaleway/scaleway-sdk-go/scw" +) + +type secretAPI interface { + GetSecret(req *smapi.GetSecretRequest, opts ...scw.RequestOption) (*smapi.Secret, error) + GetSecretByName(req *smapi.GetSecretByNameRequest, opts ...scw.RequestOption) (*smapi.Secret, error) + GetSecretVersion(req *smapi.GetSecretVersionRequest, opts ...scw.RequestOption) (*smapi.SecretVersion, error) + GetSecretVersionByName(req *smapi.GetSecretVersionByNameRequest, opts ...scw.RequestOption) (*smapi.SecretVersion, error) + AccessSecretVersion(request *smapi.AccessSecretVersionRequest, option ...scw.RequestOption) (*smapi.AccessSecretVersionResponse, error) + DisableSecretVersion(request *smapi.DisableSecretVersionRequest, option ...scw.RequestOption) (*smapi.SecretVersion, error) + ListSecrets(request *smapi.ListSecretsRequest, option ...scw.RequestOption) (*smapi.ListSecretsResponse, error) + CreateSecret(request *smapi.CreateSecretRequest, option ...scw.RequestOption) (*smapi.Secret, error) + CreateSecretVersion(request *smapi.CreateSecretVersionRequest, option ...scw.RequestOption) (*smapi.SecretVersion, error) + DeleteSecret(request *smapi.DeleteSecretRequest, option ...scw.RequestOption) error +} From c6309dac2e9c9f4ece4aa3cf2921f4aface4ab20 Mon Sep 17 00:00:00 2001 From: Moritz Johner Date: Thu, 16 Mar 2023 01:05:03 +0100 Subject: [PATCH 59/62] feat: add helm unit tests (#2113) * feat: add helm unit tests Signed-off-by: Moritz Johner * docs: add install instructions for helm-unittest Signed-off-by: Moritz Johner --------- Signed-off-by: Moritz Johner --- .github/workflows/helm.yml | 16 + Makefile | 12 + deploy/charts/external-secrets/README.md | 2 + .../__snapshot__/controller_test.yaml.snap | 38 + .../tests/__snapshot__/crds_test.yaml.snap | 2536 +++++++++++++++++ .../tests/controller_test.yaml | 34 + .../external-secrets/tests/crds_test.yaml | 27 + deploy/charts/external-secrets/values.yaml | 3 + docs/contributing/devguide.md | 6 + docs/contributing/release.md | 2 +- hack/helm.generate.sh | 6 +- 11 files changed, 2680 insertions(+), 2 deletions(-) create mode 100644 deploy/charts/external-secrets/tests/__snapshot__/controller_test.yaml.snap create mode 100644 deploy/charts/external-secrets/tests/__snapshot__/crds_test.yaml.snap create mode 100644 deploy/charts/external-secrets/tests/controller_test.yaml create mode 100644 deploy/charts/external-secrets/tests/crds_test.yaml diff --git a/.github/workflows/helm.yml b/.github/workflows/helm.yml index 4b77e5bbd79..4f3b196dfee 100644 --- a/.github/workflows/helm.yml +++ b/.github/workflows/helm.yml @@ -43,9 +43,25 @@ jobs: if [[ -n "$changed" ]]; then echo "::set-output name=changed::true" fi + - name: Install chart unittest + run: | + helm env + helm plugin install https://github.com/helm-unittest/helm-unittest - name: Run chart-testing (lint) run: ct lint --config=.github/ci/ct.yaml + - name: Create kind cluster + uses: helm/kind-action@v1.2.0 + if: steps.list-changed.outputs.changed == 'true' + + - name: Run chart-testing (install) + run: ct install --config=.github/ci/ct.yaml --charts deploy/charts/external-secrets + if: steps.list-changed.outputs.changed == 'true' + + - name: Run unitests + if: steps.list-changed.outputs.changed == 'true' + run: make helm.test + release: runs-on: ubuntu-latest steps: diff --git a/Makefile b/Makefile index 2c96695c157..9c30337c90f 100644 --- a/Makefile +++ b/Makefile @@ -185,6 +185,18 @@ helm.generate: ./hack/helm.generate.sh $(BUNDLE_DIR) $(HELM_DIR) @$(OK) Finished generating helm chart files +helm.test: helm.generate + @helm unittest --file tests/*.yaml --file 'tests/**/*.yaml' deploy/charts/external-secrets/ + +helm.update.appversion: + @chartversion=$$(yq .version ./deploy/charts/external-secrets/Chart.yaml) ; \ + chartappversion=$$(yq .appVersion ./deploy/charts/external-secrets/Chart.yaml) ; \ + chartname=$$(yq .name ./deploy/charts/external-secrets/Chart.yaml) ; \ + $(INFO) Update chartname and chartversion string in test snapshots.; \ + sed -s -i "s/^\([[:space:]]\+helm\.sh\/chart:\).*/\1 $${chartname}-$${chartversion}/" ./deploy/charts/external-secrets/tests/__snapshot__/*.yaml.snap ; \ + sed -s -i "s/^\([[:space:]]\+app\.kubernetes\.io\/version:\).*/\1 $${chartappversion}/" ./deploy/charts/external-secrets/tests/__snapshot__/*.yaml.snap ; \ + $(OK) "Version strings updated" + # ==================================================================================== # Documentation .PHONY: docs diff --git a/deploy/charts/external-secrets/README.md b/deploy/charts/external-secrets/README.md index d6d5ddd1cee..1c81ddf9b8e 100644 --- a/deploy/charts/external-secrets/README.md +++ b/deploy/charts/external-secrets/README.md @@ -77,6 +77,8 @@ The command removes all the Kubernetes components associated with the chart and | certController.tolerations | list | `[]` | | | concurrent | int | `1` | Specifies the number of concurrent ExternalSecret Reconciles external-secret executes at a time. | | controllerClass | string | `""` | If set external secrets will filter matching Secret Stores with the appropriate controller values. | +| crds.annotations | object | `{}` | | +| crds.conversion.enabled | bool | `true` | | | crds.createClusterExternalSecret | bool | `true` | If true, create CRDs for Cluster External Secret. | | crds.createClusterSecretStore | bool | `true` | If true, create CRDs for Cluster Secret Store. | | crds.createPushSecret | bool | `true` | If true, create CRDs for Push Secret. | diff --git a/deploy/charts/external-secrets/tests/__snapshot__/controller_test.yaml.snap b/deploy/charts/external-secrets/tests/__snapshot__/controller_test.yaml.snap new file mode 100644 index 00000000000..9ed92a1d23c --- /dev/null +++ b/deploy/charts/external-secrets/tests/__snapshot__/controller_test.yaml.snap @@ -0,0 +1,38 @@ +should match snapshot of default values: + 1: | + apiVersion: apps/v1 + kind: Deployment + metadata: + labels: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: external-secrets + app.kubernetes.io/version: v0.7.2 + helm.sh/chart: external-secrets-0.7.2 + name: RELEASE-NAME-external-secrets + namespace: NAMESPACE + spec: + replicas: 1 + revisionHistoryLimit: 10 + selector: + matchLabels: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/name: external-secrets + template: + metadata: + labels: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/name: external-secrets + spec: + automountServiceAccountToken: true + containers: + - args: + - --concurrent=1 + image: ghcr.io/external-secrets/external-secrets:v0.7.2 + imagePullPolicy: IfNotPresent + name: external-secrets + ports: + - containerPort: 8080 + name: metrics + protocol: TCP + serviceAccountName: RELEASE-NAME-external-secrets diff --git a/deploy/charts/external-secrets/tests/__snapshot__/crds_test.yaml.snap b/deploy/charts/external-secrets/tests/__snapshot__/crds_test.yaml.snap new file mode 100644 index 00000000000..adda344f8ec --- /dev/null +++ b/deploy/charts/external-secrets/tests/__snapshot__/crds_test.yaml.snap @@ -0,0 +1,2536 @@ +should match snapshot of default values: + 1: | + apiVersion: apiextensions.k8s.io/v1 + kind: CustomResourceDefinition + metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.3 + creationTimestamp: null + name: secretstores.external-secrets.io + spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + name: RELEASE-NAME-external-secrets-webhook + namespace: NAMESPACE + path: /convert + conversionReviewVersions: + - v1 + group: external-secrets.io + names: + categories: + - externalsecrets + kind: SecretStore + listKind: SecretStoreList + plural: secretstores + shortNames: + - ss + singular: secretstore + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Status + type: string + deprecated: true + name: v1alpha1 + schema: + openAPIV3Schema: + description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: SecretStoreSpec defines the desired state of SecretStore. + properties: + controller: + description: 'Used to select the correct KES controller (think: ingress.ingressClassName) The KES controller is instantiated with a specific controller name and filters ES based on this property' + type: string + provider: + description: Used to configure the provider. Only one provider may be set + maxProperties: 1 + minProperties: 1 + properties: + akeyless: + description: Akeyless configures this store to sync secrets using Akeyless Vault provider + properties: + akeylessGWApiURL: + description: Akeyless GW API Url from which the secrets to be fetched from. + type: string + authSecretRef: + description: Auth configures how the operator authenticates with Akeyless. + properties: + kubernetesAuth: + description: Kubernetes authenticates with Akeyless by passing the ServiceAccount token stored in the named Secret resource. + properties: + accessID: + description: the Akeyless Kubernetes auth-method access-id + type: string + k8sConfName: + description: Kubernetes-auth configuration name in Akeyless-Gateway + type: string + secretRef: + description: Optional secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Akeyless. If a name is specified without a key, `token` is the default. If one is not specified, the one bound to the controller will be used. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: Optional service account field containing the name of a kubernetes ServiceAccount. If the service account is specified, the service account secret token JWT will be used for authenticating with Akeyless. If the service account selector is not supplied, the secretRef will be used instead. + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - accessID + - k8sConfName + type: object + secretRef: + description: Reference to a Secret that contains the details to authenticate with Akeyless. + properties: + accessID: + description: The SecretAccessID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessType: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessTypeParam: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + type: object + caBundle: + description: PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + required: + - akeylessGWApiURL + - authSecretRef + type: object + alibaba: + description: Alibaba configures this store to sync secrets using Alibaba Cloud provider + properties: + auth: + description: AlibabaAuth contains a secretRef for credentials. + properties: + secretRef: + description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessKeySecretSecretRef: + description: The AccessKeySecret is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - accessKeyIDSecretRef + - accessKeySecretSecretRef + type: object + required: + - secretRef + type: object + endpoint: + type: string + regionID: + description: Alibaba Region to be used for the provider + type: string + required: + - auth + - regionID + type: object + aws: + description: AWS configures this store to sync secrets using AWS Secret Manager provider + properties: + auth: + description: 'Auth defines the information necessary to authenticate against AWS if not set aws sdk will infer credentials from your environment see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + properties: + jwt: + description: Authenticate against AWS using service account tokens. + properties: + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + type: object + secretRef: + description: AWSAuthSecretRef holds secret references for AWS credentials both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + type: object + region: + description: AWS Region to be used for the provider + type: string + role: + description: Role is a Role ARN which the SecretManager provider will assume + type: string + service: + description: Service defines which service should be used to fetch the secrets + enum: + - SecretsManager + - ParameterStore + type: string + required: + - region + - service + type: object + azurekv: + description: AzureKV configures this store to sync secrets using Azure Key Vault provider + properties: + authSecretRef: + description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. + properties: + clientId: + description: The Azure clientId of the service principle used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + clientSecret: + description: The Azure ClientSecret of the service principle used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + authType: + default: ServicePrincipal + description: 'Auth type defines how to authenticate to the keyvault service. Valid values are: - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity)' + enum: + - ServicePrincipal + - ManagedIdentity + - WorkloadIdentity + type: string + identityId: + description: If multiple Managed Identity is assigned to the pod, you can select the one to be used + type: string + serviceAccountRef: + description: ServiceAccountRef specified the service account that should be used when authenticating with WorkloadIdentity. + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + tenantId: + description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. + type: string + vaultUrl: + description: Vault Url from which the secrets to be fetched from. + type: string + required: + - vaultUrl + type: object + fake: + description: Fake configures a store with static key/value pairs + properties: + data: + items: + properties: + key: + type: string + value: + type: string + valueMap: + additionalProperties: + type: string + type: object + version: + type: string + required: + - key + type: object + type: array + required: + - data + type: object + gcpsm: + description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider + properties: + auth: + description: Auth defines the information necessary to authenticate against GCP + properties: + secretRef: + properties: + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + workloadIdentity: + properties: + clusterLocation: + type: string + clusterName: + type: string + clusterProjectID: + type: string + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - clusterLocation + - clusterName + - serviceAccountRef + type: object + type: object + projectID: + description: ProjectID project where secret is located + type: string + type: object + gitlab: + description: Gitlab configures this store to sync secrets using Gitlab Variables provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a GitLab instance. + properties: + SecretRef: + properties: + accessToken: + description: AccessToken is used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - SecretRef + type: object + projectID: + description: ProjectID specifies a project where secrets are located. + type: string + url: + description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. + type: string + required: + - auth + type: object + ibm: + description: IBM configures this store to sync secrets using IBM Cloud provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the IBM secrets manager. + properties: + secretRef: + properties: + secretApiKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + serviceUrl: + description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance + type: string + required: + - auth + type: object + kubernetes: + description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Kubernetes instance. + maxProperties: 1 + minProperties: 1 + properties: + cert: + description: has both clientCert and clientKey as secretKeySelector + properties: + clientCert: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + clientKey: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + serviceAccount: + description: points to a service account that should be used for authentication + properties: + serviceAccount: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + type: object + token: + description: use static token to authenticate with + properties: + bearerToken: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + type: object + remoteNamespace: + default: default + description: Remote namespace to fetch the secrets from + type: string + server: + description: configures the Kubernetes server Address. + properties: + caBundle: + description: CABundle is a base64-encoded CA certificate + format: byte + type: string + caProvider: + description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + url: + default: kubernetes.default + description: configures the Kubernetes server Address. + type: string + type: object + required: + - auth + type: object + oracle: + description: Oracle configures this store to sync secrets using Oracle Vault provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Oracle Vault. If empty, use the instance principal, otherwise the user credentials specified in Auth. + properties: + secretRef: + description: SecretRef to pass through sensitive information. + properties: + fingerprint: + description: Fingerprint is the fingerprint of the API private key. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + privatekey: + description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - fingerprint + - privatekey + type: object + tenancy: + description: Tenancy is the tenancy OCID where user is located. + type: string + user: + description: User is an access OCID specific to the account. + type: string + required: + - secretRef + - tenancy + - user + type: object + region: + description: Region is the region where vault is located. + type: string + vault: + description: Vault is the vault's OCID of the specific vault where secret is located. + type: string + required: + - region + - vault + type: object + vault: + description: Vault configures this store to sync secrets using Hashi provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Vault server. + properties: + appRole: + description: AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource. + properties: + path: + default: approle + description: 'Path where the App Role authentication backend is mounted in Vault, e.g: "approle"' + type: string + roleId: + description: RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault. + type: string + secretRef: + description: Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The `key` field must be specified and denotes which entry within the Secret resource is used as the app role secret. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - path + - roleId + - secretRef + type: object + cert: + description: Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate Cert authentication method + properties: + clientCert: + description: ClientCert is a certificate to authenticate using the Cert Vault authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + secretRef: + description: SecretRef to a key in a Secret resource containing client private key to authenticate with Vault using the Cert authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + jwt: + description: Jwt authenticates with Vault by passing role and JWT token using the JWT/OIDC authentication method + properties: + kubernetesServiceAccountToken: + description: Optional ServiceAccountToken specifies the Kubernetes service account for which to request a token for with the `TokenRequest` API. + properties: + audiences: + description: Optional audiences field that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to a single audience `vault` it not specified. + items: + type: string + type: array + expirationSeconds: + description: Optional expiration time in seconds that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to 10 minutes. + format: int64 + type: integer + serviceAccountRef: + description: Service account field containing the name of a kubernetes ServiceAccount. + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - serviceAccountRef + type: object + path: + default: jwt + description: 'Path where the JWT authentication backend is mounted in Vault, e.g: "jwt"' + type: string + role: + description: Role is a JWT role to authenticate using the JWT/OIDC Vault authentication method + type: string + secretRef: + description: Optional SecretRef that refers to a key in a Secret resource containing JWT token to authenticate with Vault using the JWT/OIDC authentication method. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - path + type: object + kubernetes: + description: Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server. + properties: + mountPath: + default: kubernetes + description: 'Path where the Kubernetes authentication backend is mounted in Vault, e.g: "kubernetes"' + type: string + role: + description: A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: Optional secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. If a name is specified without a key, `token` is the default. If one is not specified, the one bound to the controller will be used. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: Optional service account field containing the name of a kubernetes ServiceAccount. If the service account is specified, the service account secret token JWT will be used for authenticating with Vault. If the service account selector is not supplied, the secretRef will be used instead. + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - mountPath + - role + type: object + ldap: + description: Ldap authenticates with Vault by passing username/password pair using the LDAP authentication method + properties: + path: + default: ldap + description: 'Path where the LDAP authentication backend is mounted in Vault, e.g: "ldap"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the LDAP user used to authenticate with Vault using the LDAP authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a LDAP user name used to authenticate using the LDAP Vault authentication method + type: string + required: + - path + - username + type: object + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caBundle: + description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Vault server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + forwardInconsistent: + description: ForwardInconsistent tells Vault to forward read-after-write requests to the Vault leader instead of simply retrying within a loop. This can increase performance if the option is enabled serverside. https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header + type: boolean + namespace: + description: 'Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1". More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces' + type: string + path: + description: 'Path is the mount path of the Vault KV backend endpoint, e.g: "secret". The v2 KV secret engine version specific "/data" path suffix for fetching secrets from Vault is optional and will be appended if not present in specified path.' + type: string + readYourWrites: + description: ReadYourWrites ensures isolated read-after-write semantics by providing discovered cluster replication states in each request. More information about eventual consistency in Vault can be found here https://www.vaultproject.io/docs/enterprise/consistency + type: boolean + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + version: + default: v2 + description: Version is the Vault KV secret engine version. This can be either "v1" or "v2". Version defaults to "v2". + enum: + - v1 + - v2 + type: string + required: + - auth + - server + type: object + webhook: + description: Webhook configures this store to sync secrets using a generic templated webhook + properties: + body: + description: Body + type: string + caBundle: + description: PEM encoded CA bundle used to validate webhook server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate webhook server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + headers: + additionalProperties: + type: string + description: Headers + type: object + method: + description: Webhook Method + type: string + result: + description: Result formatting + properties: + jsonPath: + description: Json path of return value + type: string + type: object + secrets: + description: Secrets to fill in templates These secrets will be passed to the templating function as key value pairs under the given name + items: + properties: + name: + description: Name of this secret in templates + type: string + secretRef: + description: Secret ref to fill in credentials + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - name + - secretRef + type: object + type: array + timeout: + description: Timeout + type: string + url: + description: Webhook url to call + type: string + required: + - result + - url + type: object + yandexlockbox: + description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider + properties: + apiEndpoint: + description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') + type: string + auth: + description: Auth defines the information necessary to authenticate against Yandex Lockbox + properties: + authorizedKeySecretRef: + description: The authorized key used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caProvider: + description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. + properties: + certSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - auth + type: object + type: object + retrySettings: + description: Used to configure http retries if failed + properties: + maxRetries: + format: int32 + type: integer + retryInterval: + type: string + type: object + required: + - provider + type: object + status: + description: SecretStoreStatus defines the observed state of the SecretStore. + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Status + type: string + - jsonPath: .status.capabilities + name: Capabilities + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: SecretStoreSpec defines the desired state of SecretStore. + properties: + conditions: + description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore + items: + description: ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in for a ClusterSecretStore instance. + properties: + namespaceSelector: + description: Choose namespace using a labelSelector + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: Choose namespaces by name + items: + type: string + type: array + type: object + type: array + controller: + description: 'Used to select the correct KES controller (think: ingress.ingressClassName) The KES controller is instantiated with a specific controller name and filters ES based on this property' + type: string + provider: + description: Used to configure the provider. Only one provider may be set + maxProperties: 1 + minProperties: 1 + properties: + akeyless: + description: Akeyless configures this store to sync secrets using Akeyless Vault provider + properties: + akeylessGWApiURL: + description: Akeyless GW API Url from which the secrets to be fetched from. + type: string + authSecretRef: + description: Auth configures how the operator authenticates with Akeyless. + properties: + kubernetesAuth: + description: Kubernetes authenticates with Akeyless by passing the ServiceAccount token stored in the named Secret resource. + properties: + accessID: + description: the Akeyless Kubernetes auth-method access-id + type: string + k8sConfName: + description: Kubernetes-auth configuration name in Akeyless-Gateway + type: string + secretRef: + description: Optional secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Akeyless. If a name is specified without a key, `token` is the default. If one is not specified, the one bound to the controller will be used. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: Optional service account field containing the name of a kubernetes ServiceAccount. If the service account is specified, the service account secret token JWT will be used for authenticating with Akeyless. If the service account selector is not supplied, the secretRef will be used instead. + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - accessID + - k8sConfName + type: object + secretRef: + description: Reference to a Secret that contains the details to authenticate with Akeyless. + properties: + accessID: + description: The SecretAccessID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessType: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessTypeParam: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + type: object + caBundle: + description: PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. + properties: + key: + description: The key where the CA certificate can be found in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. Can only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + required: + - akeylessGWApiURL + - authSecretRef + type: object + alibaba: + description: Alibaba configures this store to sync secrets using Alibaba Cloud provider + properties: + auth: + description: AlibabaAuth contains a secretRef for credentials. + properties: + secretRef: + description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessKeySecretSecretRef: + description: The AccessKeySecret is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - accessKeyIDSecretRef + - accessKeySecretSecretRef + type: object + required: + - secretRef + type: object + endpoint: + type: string + regionID: + description: Alibaba Region to be used for the provider + type: string + required: + - auth + - regionID + type: object + aws: + description: AWS configures this store to sync secrets using AWS Secret Manager provider + properties: + additionalRoles: + description: AdditionalRoles is a chained list of Role ARNs which the SecretManager provider will sequentially assume before assuming Role + items: + type: string + type: array + auth: + description: 'Auth defines the information necessary to authenticate against AWS if not set aws sdk will infer credentials from your environment see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + properties: + jwt: + description: Authenticate against AWS using service account tokens. + properties: + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + type: object + secretRef: + description: AWSAuthSecretRef holds secret references for AWS credentials both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + sessionTokenSecretRef: + description: 'The SessionToken used for authentication This must be defined if AccessKeyID and SecretAccessKey are temporary credentials see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html' + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + type: object + region: + description: AWS Region to be used for the provider + type: string + role: + description: Role is a Role ARN which the SecretManager provider will assume + type: string + service: + description: Service defines which service should be used to fetch the secrets + enum: + - SecretsManager + - ParameterStore + type: string + required: + - region + - service + type: object + azurekv: + description: AzureKV configures this store to sync secrets using Azure Key Vault provider + properties: + authSecretRef: + description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. + properties: + clientId: + description: The Azure clientId of the service principle used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + clientSecret: + description: The Azure ClientSecret of the service principle used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + authType: + default: ServicePrincipal + description: 'Auth type defines how to authenticate to the keyvault service. Valid values are: - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity)' + enum: + - ServicePrincipal + - ManagedIdentity + - WorkloadIdentity + type: string + environmentType: + default: PublicCloud + description: 'EnvironmentType specifies the Azure cloud environment endpoints to use for connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud' + enum: + - PublicCloud + - USGovernmentCloud + - ChinaCloud + - GermanCloud + type: string + identityId: + description: If multiple Managed Identity is assigned to the pod, you can select the one to be used + type: string + serviceAccountRef: + description: ServiceAccountRef specified the service account that should be used when authenticating with WorkloadIdentity. + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + tenantId: + description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. + type: string + vaultUrl: + description: Vault Url from which the secrets to be fetched from. + type: string + required: + - vaultUrl + type: object + doppler: + description: Doppler configures this store to sync secrets using the Doppler provider + properties: + auth: + description: Auth configures how the Operator authenticates with the Doppler API + properties: + secretRef: + properties: + dopplerToken: + description: The DopplerToken is used for authentication. See https://docs.doppler.com/reference/api#authentication for auth token types. The Key attribute defaults to dopplerToken if not specified. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - dopplerToken + type: object + required: + - secretRef + type: object + config: + description: Doppler config (required if not using a Service Token) + type: string + format: + description: Format enables the downloading of secrets as a file (string) + enum: + - json + - dotnet-json + - env + - yaml + - docker + type: string + nameTransformer: + description: Environment variable compatible name transforms that change secret names to a different format + enum: + - upper-camel + - camel + - lower-snake + - tf-var + - dotnet-env + type: string + project: + description: Doppler project (required if not using a Service Token) + type: string + required: + - auth + type: object + fake: + description: Fake configures a store with static key/value pairs + properties: + data: + items: + properties: + key: + type: string + value: + type: string + valueMap: + additionalProperties: + type: string + type: object + version: + type: string + required: + - key + type: object + type: array + required: + - data + type: object + gcpsm: + description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider + properties: + auth: + description: Auth defines the information necessary to authenticate against GCP + properties: + secretRef: + properties: + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + workloadIdentity: + properties: + clusterLocation: + type: string + clusterName: + type: string + clusterProjectID: + type: string + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - clusterLocation + - clusterName + - serviceAccountRef + type: object + type: object + projectID: + description: ProjectID project where secret is located + type: string + type: object + gitlab: + description: Gitlab configures this store to sync secrets using Gitlab Variables provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a GitLab instance. + properties: + SecretRef: + properties: + accessToken: + description: AccessToken is used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - SecretRef + type: object + environment: + description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) + type: string + groupIDs: + description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. + items: + type: string + type: array + inheritFromGroups: + description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. + type: boolean + projectID: + description: ProjectID specifies a project where secrets are located. + type: string + url: + description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. + type: string + required: + - auth + type: object + ibm: + description: IBM configures this store to sync secrets using IBM Cloud provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the IBM secrets manager. + maxProperties: 1 + minProperties: 1 + properties: + containerAuth: + description: IBM Container-based auth with IAM Trusted Profile. + properties: + iamEndpoint: + type: string + profile: + description: the IBM Trusted Profile + type: string + tokenLocation: + description: Location the token is mounted on the pod + type: string + required: + - profile + type: object + secretRef: + properties: + secretApiKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + type: object + serviceUrl: + description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance + type: string + required: + - auth + type: object + keepersecurity: + description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider + properties: + authRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + folderID: + type: string + required: + - authRef + - folderID + type: object + kubernetes: + description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Kubernetes instance. + maxProperties: 1 + minProperties: 1 + properties: + cert: + description: has both clientCert and clientKey as secretKeySelector + properties: + clientCert: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + clientKey: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + serviceAccount: + description: points to a service account that should be used for authentication + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + token: + description: use static token to authenticate with + properties: + bearerToken: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + type: object + remoteNamespace: + default: default + description: Remote namespace to fetch the secrets from + type: string + server: + description: configures the Kubernetes server Address. + properties: + caBundle: + description: CABundle is a base64-encoded CA certificate + format: byte + type: string + caProvider: + description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' + properties: + key: + description: The key where the CA certificate can be found in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. Can only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + url: + default: kubernetes.default + description: configures the Kubernetes server Address. + type: string + type: object + required: + - auth + type: object + onepassword: + description: OnePassword configures this store to sync secrets using the 1Password Cloud provider + properties: + auth: + description: Auth defines the information necessary to authenticate against OnePassword Connect Server + properties: + secretRef: + description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. + properties: + connectTokenSecretRef: + description: The ConnectToken is used for authentication to a 1Password Connect Server. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - connectTokenSecretRef + type: object + required: + - secretRef + type: object + connectHost: + description: ConnectHost defines the OnePassword Connect Server to connect to + type: string + vaults: + additionalProperties: + type: integer + description: Vaults defines which OnePassword vaults to search in which order + type: object + required: + - auth + - connectHost + - vaults + type: object + oracle: + description: Oracle configures this store to sync secrets using Oracle Vault provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Oracle Vault. If empty, use the instance principal, otherwise the user credentials specified in Auth. + properties: + secretRef: + description: SecretRef to pass through sensitive information. + properties: + fingerprint: + description: Fingerprint is the fingerprint of the API private key. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + privatekey: + description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - fingerprint + - privatekey + type: object + tenancy: + description: Tenancy is the tenancy OCID where user is located. + type: string + user: + description: User is an access OCID specific to the account. + type: string + required: + - secretRef + - tenancy + - user + type: object + region: + description: Region is the region where vault is located. + type: string + vault: + description: Vault is the vault's OCID of the specific vault where secret is located. + type: string + required: + - region + - vault + type: object + senhasegura: + description: Senhasegura configures this store to sync secrets using senhasegura provider + properties: + auth: + description: Auth defines parameters to authenticate in senhasegura + properties: + clientId: + type: string + clientSecretSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecretSecretRef + type: object + ignoreSslCertificate: + default: false + description: IgnoreSslCertificate defines if SSL certificate must be ignored + type: boolean + module: + description: Module defines which senhasegura module should be used to get secrets + type: string + url: + description: URL of senhasegura + type: string + required: + - auth + - module + - url + type: object + vault: + description: Vault configures this store to sync secrets using Hashi provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Vault server. + properties: + appRole: + description: AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource. + properties: + path: + default: approle + description: 'Path where the App Role authentication backend is mounted in Vault, e.g: "approle"' + type: string + roleId: + description: RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault. + type: string + secretRef: + description: Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The `key` field must be specified and denotes which entry within the Secret resource is used as the app role secret. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - path + - roleId + - secretRef + type: object + cert: + description: Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate Cert authentication method + properties: + clientCert: + description: ClientCert is a certificate to authenticate using the Cert Vault authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + secretRef: + description: SecretRef to a key in a Secret resource containing client private key to authenticate with Vault using the Cert authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + jwt: + description: Jwt authenticates with Vault by passing role and JWT token using the JWT/OIDC authentication method + properties: + kubernetesServiceAccountToken: + description: Optional ServiceAccountToken specifies the Kubernetes service account for which to request a token for with the `TokenRequest` API. + properties: + audiences: + description: 'Optional audiences field that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to a single audience `vault` it not specified. Deprecated: use serviceAccountRef.Audiences instead' + items: + type: string + type: array + expirationSeconds: + description: 'Optional expiration time in seconds that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Deprecated: this will be removed in the future. Defaults to 10 minutes.' + format: int64 + type: integer + serviceAccountRef: + description: Service account field containing the name of a kubernetes ServiceAccount. + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - serviceAccountRef + type: object + path: + default: jwt + description: 'Path where the JWT authentication backend is mounted in Vault, e.g: "jwt"' + type: string + role: + description: Role is a JWT role to authenticate using the JWT/OIDC Vault authentication method + type: string + secretRef: + description: Optional SecretRef that refers to a key in a Secret resource containing JWT token to authenticate with Vault using the JWT/OIDC authentication method. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - path + type: object + kubernetes: + description: Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server. + properties: + mountPath: + default: kubernetes + description: 'Path where the Kubernetes authentication backend is mounted in Vault, e.g: "kubernetes"' + type: string + role: + description: A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: Optional secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. If a name is specified without a key, `token` is the default. If one is not specified, the one bound to the controller will be used. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: Optional service account field containing the name of a kubernetes ServiceAccount. If the service account is specified, the service account secret token JWT will be used for authenticating with Vault. If the service account selector is not supplied, the secretRef will be used instead. + properties: + audiences: + description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - mountPath + - role + type: object + ldap: + description: Ldap authenticates with Vault by passing username/password pair using the LDAP authentication method + properties: + path: + default: ldap + description: 'Path where the LDAP authentication backend is mounted in Vault, e.g: "ldap"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the LDAP user used to authenticate with Vault using the LDAP authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a LDAP user name used to authenticate using the LDAP Vault authentication method + type: string + required: + - path + - username + type: object + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caBundle: + description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Vault server certificate. + properties: + key: + description: The key where the CA certificate can be found in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. Can only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + forwardInconsistent: + description: ForwardInconsistent tells Vault to forward read-after-write requests to the Vault leader instead of simply retrying within a loop. This can increase performance if the option is enabled serverside. https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header + type: boolean + namespace: + description: 'Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1". More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces' + type: string + path: + description: 'Path is the mount path of the Vault KV backend endpoint, e.g: "secret". The v2 KV secret engine version specific "/data" path suffix for fetching secrets from Vault is optional and will be appended if not present in specified path.' + type: string + readYourWrites: + description: ReadYourWrites ensures isolated read-after-write semantics by providing discovered cluster replication states in each request. More information about eventual consistency in Vault can be found here https://www.vaultproject.io/docs/enterprise/consistency + type: boolean + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + version: + default: v2 + description: Version is the Vault KV secret engine version. This can be either "v1" or "v2". Version defaults to "v2". + enum: + - v1 + - v2 + type: string + required: + - auth + - server + type: object + webhook: + description: Webhook configures this store to sync secrets using a generic templated webhook + properties: + body: + description: Body + type: string + caBundle: + description: PEM encoded CA bundle used to validate webhook server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate webhook server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + headers: + additionalProperties: + type: string + description: Headers + type: object + method: + description: Webhook Method + type: string + result: + description: Result formatting + properties: + jsonPath: + description: Json path of return value + type: string + type: object + secrets: + description: Secrets to fill in templates These secrets will be passed to the templating function as key value pairs under the given name + items: + properties: + name: + description: Name of this secret in templates + type: string + secretRef: + description: Secret ref to fill in credentials + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - name + - secretRef + type: object + type: array + timeout: + description: Timeout + type: string + url: + description: Webhook url to call + type: string + required: + - result + - url + type: object + yandexcertificatemanager: + description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider + properties: + apiEndpoint: + description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') + type: string + auth: + description: Auth defines the information necessary to authenticate against Yandex Certificate Manager + properties: + authorizedKeySecretRef: + description: The authorized key used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caProvider: + description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. + properties: + certSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - auth + type: object + yandexlockbox: + description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider + properties: + apiEndpoint: + description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') + type: string + auth: + description: Auth defines the information necessary to authenticate against Yandex Lockbox + properties: + authorizedKeySecretRef: + description: The authorized key used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caProvider: + description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. + properties: + certSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - auth + type: object + type: object + refreshInterval: + description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. + type: integer + retrySettings: + description: Used to configure http retries if failed + properties: + maxRetries: + format: int32 + type: integer + retryInterval: + type: string + type: object + required: + - provider + type: object + status: + description: SecretStoreStatus defines the observed state of the SecretStore. + properties: + capabilities: + description: SecretStoreCapabilities defines the possible operations a SecretStore can do. + type: string + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/deploy/charts/external-secrets/tests/controller_test.yaml b/deploy/charts/external-secrets/tests/controller_test.yaml new file mode 100644 index 00000000000..1a61e75fbdd --- /dev/null +++ b/deploy/charts/external-secrets/tests/controller_test.yaml @@ -0,0 +1,34 @@ +suite: test controller deployment +templates: + - deployment.yaml +tests: + - it: should match snapshot of default values + asserts: + - matchSnapshot: {} + - it: should set imagePullPolicy to Always + set: + image.pullPolicy: Always + asserts: + - equal: + path: spec.template.spec.containers[0].imagePullPolicy + value: Always + - it: should imagePullPolicy to be default value IfNotPresent + asserts: + - equal: + path: spec.template.spec.containers[0].imagePullPolicy + value: IfNotPresent + - it: should override securityContext + set: + podSecurityContext: + runAsUser: 2000 + securityContext: + runAsUser: 3000 + asserts: + - equal: + path: spec.template.spec.securityContext + value: + runAsUser: 2000 + - equal: + path: spec.template.spec.containers[0].securityContext + value: + runAsUser: 3000 diff --git a/deploy/charts/external-secrets/tests/crds_test.yaml b/deploy/charts/external-secrets/tests/crds_test.yaml new file mode 100644 index 00000000000..25a18c78a28 --- /dev/null +++ b/deploy/charts/external-secrets/tests/crds_test.yaml @@ -0,0 +1,27 @@ +suite: test crds +templates: + - crds/secretstore.yaml +tests: + - it: should match snapshot of default values + asserts: + - matchSnapshot: {} + - it: should disable conversion webhook + set: + crds.conversion.enabled: false + asserts: + - isNull: + path: spec.conversion + + - it: should add annotations + set: + crds: + annotations: + foo: bar + baz: bang + asserts: + - equal: + path: metadata.annotations.foo + value: bar + - equal: + path: metadata.annotations.baz + value: bang diff --git a/deploy/charts/external-secrets/values.yaml b/deploy/charts/external-secrets/values.yaml index 7288e302a91..852b9b317f3 100644 --- a/deploy/charts/external-secrets/values.yaml +++ b/deploy/charts/external-secrets/values.yaml @@ -22,6 +22,9 @@ crds: createClusterSecretStore: true # -- If true, create CRDs for Push Secret. createPushSecret: true + annotations: {} + conversion: + enabled: true imagePullSecrets: [] nameOverride: "" diff --git a/docs/contributing/devguide.md b/docs/contributing/devguide.md index 5d1747c16b6..2a9743fa070 100644 --- a/docs/contributing/devguide.md +++ b/docs/contributing/devguide.md @@ -32,6 +32,12 @@ source <(setup-envtest use 1.20.2 -p env --os $(go env GOOS) --arch $(go env GOA for more information, please see [setup-envtest docs](https://github.com/kubernetes-sigs/controller-runtime/tree/master/tools/setup-envtest) +Our helm chart is tested using `helm-unittest`. You will need it to run tests locally if you modify the helm chart. Install it with the following command: + +``` +$ helm plugin install https://github.com/helm-unittest/helm-unittest +``` + ## Building & Testing The project uses the `make` build system. It'll run code generators, tests and diff --git a/docs/contributing/release.md b/docs/contributing/release.md index 7fd590284e5..66047fdd5a0 100644 --- a/docs/contributing/release.md +++ b/docs/contributing/release.md @@ -12,7 +12,7 @@ The external-secrets project is released on a as-needed basis. Feel free to open ## Release Helm Chart -1. Update `version` and/or `appVersion` in `Chart.yaml` and run `make helm.docs` +1. Update `version` and/or `appVersion` in `Chart.yaml` and run `make helm.docs helm.update.appversion` 1. push to branch and open pr 1. run `/ok-to-test-managed` commands for all cloud providers 1. merge PR if everyhing is green diff --git a/hack/helm.generate.sh b/hack/helm.generate.sh index e759b117ed0..e72760c7812 100755 --- a/hack/helm.generate.sh +++ b/hack/helm.generate.sh @@ -21,7 +21,7 @@ for i in "${HELM_DIR}"/templates/crds/*.yml; do cp "$i" "$i.bkp" if [[ "$CRDS_FLAG_NAME" == *"Cluster"* ]]; then echo "{{- if and (.Values.installCRDs) (.Values.crds.$CRDS_FLAG_NAME) }}" > "$i" - elif [[ "$CRDS_FLAG_NAME" == *"PushSecret"* ]]; then + elif [[ "$CRDS_FLAG_NAME" == *"PushSecret"* ]]; then echo "{{- if and (.Values.installCRDs) (.Values.crds.$CRDS_FLAG_NAME) }}" > "$i" else echo "{{- if .Values.installCRDs }}" > "$i" @@ -31,5 +31,9 @@ for i in "${HELM_DIR}"/templates/crds/*.yml; do rm "$i.bkp" $SEDPRG -i 's/name: kubernetes/name: {{ include "external-secrets.fullname" . }}-webhook/g' "$i" $SEDPRG -i 's/namespace: default/namespace: {{ .Release.Namespace | quote }}/g' "$i" + $SEDPRG -i '0,/annotations/!b;//a\ {{- with .Values.crds.annotations }}\n {{- toYaml . | nindent 4}}\n {{- end }}' "$i" + + sed -i '/ conversion:/i{{- if .Values.crds.conversion.enabled }}' "$i" + echo "{{- end }}" >> "$i" mv "$i" "${i%.yml}.yaml" done \ No newline at end of file From a3f43c629c6f818426de89dd4fce1c824b4cf9f0 Mon Sep 17 00:00:00 2001 From: Aleksey Zhukov <353748+alezkv@users.noreply.github.com> Date: Thu, 16 Mar 2023 22:43:40 +0100 Subject: [PATCH 60/62] Fix typo in docs link: odic -> oidc (#2132) --- docs/provider/hashicorp-vault.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/provider/hashicorp-vault.md b/docs/provider/hashicorp-vault.md index bb547f5e035..891666a6403 100644 --- a/docs/provider/hashicorp-vault.md +++ b/docs/provider/hashicorp-vault.md @@ -272,7 +272,7 @@ We support five different modes for authentication: [appRole](https://www.vaultproject.io/docs/auth/approle), [kubernetes-native](https://www.vaultproject.io/docs/auth/kubernetes), [ldap](https://www.vaultproject.io/docs/auth/ldap) and -[jwt/odic](https://www.vaultproject.io/docs/auth/jwt), each one comes with it's own +[jwt/oidc](https://www.vaultproject.io/docs/auth/jwt), each one comes with it's own trade-offs. Depending on the authentication method you need to adapt your environment. #### Token-based authentication From b9297c3502a6df445084f379574168602e6503c4 Mon Sep 17 00:00:00 2001 From: Gustavo Fernandes de Carvalho Date: Thu, 16 Mar 2023 20:31:30 -0300 Subject: [PATCH 61/62] :broom: bump 0.8.0 (#2134) * chore: bump 0.8.0 Signed-off-by: Gustavo Carvalho * Adding command to update crds snapshot. Updating CRDs snapshot and test snapshot Signed-off-by: Gustavo Carvalho --------- Signed-off-by: Gustavo Carvalho --- Makefile | 4 ++ deploy/charts/external-secrets/Chart.yaml | 4 +- deploy/charts/external-secrets/README.md | 2 +- .../__snapshot__/controller_test.yaml.snap | 6 +- .../tests/__snapshot__/crds_test.yaml.snap | 58 +++++++++++++++++++ 5 files changed, 68 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 9c30337c90f..17a6de674dc 100644 --- a/Makefile +++ b/Makefile @@ -188,6 +188,9 @@ helm.generate: helm.test: helm.generate @helm unittest --file tests/*.yaml --file 'tests/**/*.yaml' deploy/charts/external-secrets/ +helm.test.update: helm.generate + @helm unittest -u --file tests/*.yaml --file 'tests/**/*.yaml' deploy/charts/external-secrets/ + helm.update.appversion: @chartversion=$$(yq .version ./deploy/charts/external-secrets/Chart.yaml) ; \ chartappversion=$$(yq .appVersion ./deploy/charts/external-secrets/Chart.yaml) ; \ @@ -195,6 +198,7 @@ helm.update.appversion: $(INFO) Update chartname and chartversion string in test snapshots.; \ sed -s -i "s/^\([[:space:]]\+helm\.sh\/chart:\).*/\1 $${chartname}-$${chartversion}/" ./deploy/charts/external-secrets/tests/__snapshot__/*.yaml.snap ; \ sed -s -i "s/^\([[:space:]]\+app\.kubernetes\.io\/version:\).*/\1 $${chartappversion}/" ./deploy/charts/external-secrets/tests/__snapshot__/*.yaml.snap ; \ + sed -s -i "s/^\([[:space:]]\+image: ghcr\.io\/external-secrets\/external-secrets:\).*/\1$${chartappversion}/" ./deploy/charts/external-secrets/tests/__snapshot__/*.yaml.snap ; \ $(OK) "Version strings updated" # ==================================================================================== diff --git a/deploy/charts/external-secrets/Chart.yaml b/deploy/charts/external-secrets/Chart.yaml index 05bc7633339..e0e471b099c 100644 --- a/deploy/charts/external-secrets/Chart.yaml +++ b/deploy/charts/external-secrets/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: external-secrets description: External secret management for Kubernetes type: application -version: "0.7.2" -appVersion: "v0.7.2" +version: "0.8.0" +appVersion: "v0.8.0" kubeVersion: ">= 1.19.0-0" keywords: - kubernetes-external-secrets diff --git a/deploy/charts/external-secrets/README.md b/deploy/charts/external-secrets/README.md index 1c81ddf9b8e..8f8b9933c1a 100644 --- a/deploy/charts/external-secrets/README.md +++ b/deploy/charts/external-secrets/README.md @@ -4,7 +4,7 @@ [//]: # (README.md generated by gotmpl. DO NOT EDIT.) -![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![Version: 0.7.2](https://img.shields.io/badge/Version-0.7.2-informational?style=flat-square) +![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![Version: 0.8.0](https://img.shields.io/badge/Version-0.8.0-informational?style=flat-square) External secret management for Kubernetes diff --git a/deploy/charts/external-secrets/tests/__snapshot__/controller_test.yaml.snap b/deploy/charts/external-secrets/tests/__snapshot__/controller_test.yaml.snap index 9ed92a1d23c..7a380d283f2 100644 --- a/deploy/charts/external-secrets/tests/__snapshot__/controller_test.yaml.snap +++ b/deploy/charts/external-secrets/tests/__snapshot__/controller_test.yaml.snap @@ -7,8 +7,8 @@ should match snapshot of default values: app.kubernetes.io/instance: RELEASE-NAME app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: external-secrets - app.kubernetes.io/version: v0.7.2 - helm.sh/chart: external-secrets-0.7.2 + app.kubernetes.io/version: v0.8.0 + helm.sh/chart: external-secrets-0.8.0 name: RELEASE-NAME-external-secrets namespace: NAMESPACE spec: @@ -28,7 +28,7 @@ should match snapshot of default values: containers: - args: - --concurrent=1 - image: ghcr.io/external-secrets/external-secrets:v0.7.2 + image: ghcr.io/external-secrets/external-secrets:v0.8.0 imagePullPolicy: IfNotPresent name: external-secrets ports: diff --git a/deploy/charts/external-secrets/tests/__snapshot__/crds_test.yaml.snap b/deploy/charts/external-secrets/tests/__snapshot__/crds_test.yaml.snap index adda344f8ec..64664197f27 100644 --- a/deploy/charts/external-secrets/tests/__snapshot__/crds_test.yaml.snap +++ b/deploy/charts/external-secrets/tests/__snapshot__/crds_test.yaml.snap @@ -2020,6 +2020,64 @@ should match snapshot of default values: - region - vault type: object + scaleway: + description: Scaleway + properties: + accessKey: + description: AccessKey is the non-secret part of the api key. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + apiUrl: + description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com + type: string + projectId: + description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' + type: string + region: + description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' + type: string + secretKey: + description: SecretKey is the non-secret part of the api key. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + required: + - accessKey + - projectId + - region + - secretKey + type: object senhasegura: description: Senhasegura configures this store to sync secrets using senhasegura provider properties: From a0d2aef2e35c259c9ee75d65f7587e6ed71ef2ad Mon Sep 17 00:00:00 2001 From: Gustavo Fernandes de Carvalho Date: Fri, 17 Mar 2023 19:59:24 -0300 Subject: [PATCH 62/62] :bug: fixing servicemonitor bug in 0.8.0 (#2136) * fix: removing service monitor duplicate definition Signed-off-by: Gustavo Carvalho * Adding new command to a helm release Signed-off-by: Gustavo Carvalho * Adding also servicemonitor.yaml fixes Signed-off-by: Gustavo Carvalho --------- Signed-off-by: Gustavo Carvalho --- .../cert-controller-servicemonitor.yaml | 38 ------------------- .../templates/servicemonitor.yaml | 1 + .../templates/webhook-servicemonitor.yaml | 38 ------------------- docs/contributing/release.md | 1 + 4 files changed, 2 insertions(+), 76 deletions(-) delete mode 100644 deploy/charts/external-secrets/templates/cert-controller-servicemonitor.yaml delete mode 100644 deploy/charts/external-secrets/templates/webhook-servicemonitor.yaml diff --git a/deploy/charts/external-secrets/templates/cert-controller-servicemonitor.yaml b/deploy/charts/external-secrets/templates/cert-controller-servicemonitor.yaml deleted file mode 100644 index 78e2388c849..00000000000 --- a/deploy/charts/external-secrets/templates/cert-controller-servicemonitor.yaml +++ /dev/null @@ -1,38 +0,0 @@ -{{- if and .Values.certController.create .Values.certController.serviceMonitor.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics - labels: - {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 4 }} -spec: - type: ClusterIP - ports: - - port: 8080 - protocol: TCP - name: metrics - selector: - {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 4 }} ---- -apiVersion: "monitoring.coreos.com/v1" -kind: ServiceMonitor -metadata: - labels: - {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} -{{- if .Values.certController.serviceMonitor.additionalLabels }} -{{ toYaml .Values.certController.serviceMonitor.additionalLabels | indent 4 }} -{{- end }} - name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics - namespace: {{ .Release.Namespace | quote }} -spec: - selector: - matchLabels: - {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 6 }} - namespaceSelector: - matchNames: - - {{ .Release.Namespace | quote }} - endpoints: - - port: metrics - interval: {{ .Values.certController.serviceMonitor.interval }} - scrapeTimeout: {{ .Values.certController.serviceMonitor.scrapeTimeout }} -{{- end }} diff --git a/deploy/charts/external-secrets/templates/servicemonitor.yaml b/deploy/charts/external-secrets/templates/servicemonitor.yaml index 6b09df5a9d0..69cbd5c88f8 100644 --- a/deploy/charts/external-secrets/templates/servicemonitor.yaml +++ b/deploy/charts/external-secrets/templates/servicemonitor.yaml @@ -94,6 +94,7 @@ spec: {{- toYaml . | nindent 6 }} {{- end }} {{- end }} +--- {{- if .Values.certController.create }} apiVersion: v1 kind: Service diff --git a/deploy/charts/external-secrets/templates/webhook-servicemonitor.yaml b/deploy/charts/external-secrets/templates/webhook-servicemonitor.yaml deleted file mode 100644 index 4843406b27e..00000000000 --- a/deploy/charts/external-secrets/templates/webhook-servicemonitor.yaml +++ /dev/null @@ -1,38 +0,0 @@ -{{- if and .Values.webhook.create .Values.webhook.serviceMonitor.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ include "external-secrets.fullname" . }}-webhook-metrics - labels: - {{- include "external-secrets-webhook.selectorLabels" . | nindent 4 }} -spec: - type: ClusterIP - ports: - - port: 8080 - protocol: TCP - name: metrics - selector: - {{- include "external-secrets-webhook.selectorLabels" . | nindent 4 }} ---- -apiVersion: "monitoring.coreos.com/v1" -kind: ServiceMonitor -metadata: - labels: - {{- include "external-secrets-webhook.labels" . | nindent 4 }} -{{- if .Values.webhook.serviceMonitor.additionalLabels }} -{{ toYaml .Values.webhook.serviceMonitor.additionalLabels | indent 4 }} -{{- end }} - name: {{ include "external-secrets.fullname" . }}-webhook-metrics - namespace: {{ .Release.Namespace | quote }} -spec: - selector: - matchLabels: - {{- include "external-secrets-webhook.selectorLabels" . | nindent 6 }} - namespaceSelector: - matchNames: - - {{ .Release.Namespace | quote }} - endpoints: - - port: metrics - interval: {{ .Values.webhook.serviceMonitor.interval }} - scrapeTimeout: {{ .Values.webhook.serviceMonitor.scrapeTimeout }} -{{- end }} diff --git a/docs/contributing/release.md b/docs/contributing/release.md index 66047fdd5a0..00587f1aa26 100644 --- a/docs/contributing/release.md +++ b/docs/contributing/release.md @@ -13,6 +13,7 @@ The external-secrets project is released on a as-needed basis. Feel free to open ## Release Helm Chart 1. Update `version` and/or `appVersion` in `Chart.yaml` and run `make helm.docs helm.update.appversion` +1. If there is any CRD change, run `make helm.test.update` and `make helm.test` 1. push to branch and open pr 1. run `/ok-to-test-managed` commands for all cloud providers 1. merge PR if everyhing is green