Browse Source

Merge branch 'main' into beach-team

Signed-off-by: Gustavo Carvalho <gusfcarvalho@gmail.com>
Gustavo Carvalho 3 years ago
parent
commit
e54347aca6
82 changed files with 1792 additions and 290 deletions
  1. 1 1
      .github/workflows/ci.yml
  2. 2 2
      .github/workflows/e2e.yml
  3. 2 2
      .github/workflows/helm.yml
  4. 1 1
      .github/workflows/release.yml
  5. 1 1
      Dockerfile.standalone
  6. 3 37
      Makefile
  7. 1 1
      apis/externalsecrets/v1alpha1/secretstore_azurekv_types.go
  8. 22 4
      apis/externalsecrets/v1beta1/externalsecret_types.go
  9. 1 1
      apis/externalsecrets/v1beta1/secretstore_azurekv_types.go
  10. 15 2
      apis/externalsecrets/v1beta1/secretstore_ibm_types.go
  11. 28 0
      apis/externalsecrets/v1beta1/secretstore_types.go
  12. 0 25
      apis/externalsecrets/v1beta1/secretstore_vault_types.go
  13. 58 0
      apis/externalsecrets/v1beta1/zz_generated.deepcopy.go
  14. 32 18
      cmd/root.go
  15. 34 6
      config/crds/bases/external-secrets.io_clusterexternalsecrets.yaml
  16. 26 8
      config/crds/bases/external-secrets.io_clustersecretstores.yaml
  17. 32 6
      config/crds/bases/external-secrets.io_externalsecrets.yaml
  18. 26 8
      config/crds/bases/external-secrets.io_secretstores.yaml
  19. 8 0
      config/crds/bases/kustomization.yaml
  20. 2 2
      deploy/charts/external-secrets/Chart.yaml
  21. 10 0
      deploy/charts/external-secrets/README.md
  22. 0 1
      deploy/charts/external-secrets/README.md.gotmpl
  23. 13 2
      deploy/charts/external-secrets/templates/cert-controller-service.yaml
  24. 4 0
      deploy/charts/external-secrets/templates/deployment.yaml
  25. 13 2
      deploy/charts/external-secrets/templates/service.yaml
  26. 14 4
      deploy/charts/external-secrets/templates/webhook-service.yaml
  27. 37 0
      deploy/charts/external-secrets/values.yaml
  28. 95 26
      deploy/crds/bundle.yaml
  29. 105 0
      docs/guides-datafrom-rewrite.md
  30. 7 2
      docs/guides-getallsecrets.md
  31. 2 0
      docs/guides-metrics.md
  32. BIN
      docs/pictures/screenshot_container_auth_create_1.png
  33. BIN
      docs/pictures/screenshot_container_auth_create_2.png
  34. BIN
      docs/pictures/screenshot_container_auth_create_3.png
  35. BIN
      docs/pictures/screenshot_container_auth_create_button.png
  36. BIN
      docs/pictures/screenshot_container_auth_create_group.png
  37. BIN
      docs/pictures/screenshot_container_auth_create_group_1.png
  38. BIN
      docs/pictures/screenshot_container_auth_create_group_2.png
  39. BIN
      docs/pictures/screenshot_container_auth_create_group_3.png
  40. BIN
      docs/pictures/screenshot_container_auth_create_group_4.png
  41. BIN
      docs/pictures/screenshot_container_auth_iam_left.png
  42. 1 1
      docs/provider-1password-automation.md
  43. 21 7
      docs/provider-azure-key-vault.md
  44. 66 7
      docs/provider-ibm-secrets-manager.md
  45. 24 0
      docs/snippets/azkv-pkcs12-cert-external-secret.yaml
  46. 24 0
      docs/snippets/datafrom-rewrite-conflict.yaml
  47. 18 0
      docs/snippets/datafrom-rewrite-invalid-characters.yaml
  48. 20 0
      docs/snippets/datafrom-rewrite-remove-path.yaml
  49. 14 0
      docs/snippets/full-external-secret.yaml
  50. 22 0
      docs/snippets/ibm-container-auth-volume.yaml
  51. 4 0
      docs/snippets/ibm-secret-store.yaml
  52. 216 11
      docs/spec.md
  53. 0 1
      e2e/run.sh
  54. 1 0
      e2e/suites/provider/cases/akeyless/akeyless.go
  55. 1 0
      e2e/suites/provider/cases/alibaba/alibaba.go
  56. 1 0
      e2e/suites/provider/cases/aws/parameterstore/parameterstore.go
  57. 1 0
      e2e/suites/provider/cases/aws/secretsmanager/secretsmanager.go
  58. 1 0
      e2e/suites/provider/cases/azure/azure_secret.go
  59. 37 0
      e2e/suites/provider/cases/common/common.go
  60. 50 2
      e2e/suites/provider/cases/common/find_by_name.go
  61. 2 0
      e2e/suites/provider/cases/gcp/gcp.go
  62. 1 0
      e2e/suites/provider/cases/gitlab/gitlab.go
  63. 1 0
      e2e/suites/provider/cases/kubernetes/kubernetes.go
  64. 1 0
      e2e/suites/provider/cases/oracle/oracle.go
  65. 12 0
      e2e/suites/provider/cases/vault/vault.go
  66. 17 17
      go.mod
  67. 45 38
      go.sum
  68. 7 0
      hack/api-docs/mkdocs.yml
  69. 33 0
      hack/crd.generate.sh
  70. 35 0
      hack/helm.generate.sh
  71. 2 0
      pkg/controllers/clusterexternalsecret/clusterexternalsecret_controller.go
  72. 26 5
      pkg/controllers/externalsecret/externalsecret_controller.go
  73. 168 0
      pkg/controllers/externalsecret/externalsecret_controller_test.go
  74. 5 1
      pkg/provider/akeyless/akeyless_api.go
  75. 68 19
      pkg/provider/ibm/provider.go
  76. 13 0
      pkg/provider/ibm/provider_test.go
  77. 21 4
      pkg/provider/onepassword/fake/fake.go
  78. 7 14
      pkg/provider/onepassword/onepassword.go
  79. 1 1
      pkg/provider/onepassword/onepassword_test.go
  80. 3 0
      pkg/provider/vault/vault.go
  81. 49 0
      pkg/utils/utils.go
  82. 158 0
      pkg/utils/utils_test.go

+ 1 - 1
.github/workflows/ci.yml

@@ -259,7 +259,7 @@ jobs:
 
 
       - name: Install cosign
       - name: Install cosign
         if: github.ref == 'refs/heads/main' && env.GHCR_USERNAME != ''
         if: github.ref == 'refs/heads/main' && env.GHCR_USERNAME != ''
-        uses: sigstore/cosign-installer@v2.4.1
+        uses: sigstore/cosign-installer@v2.5.0
 
 
       - name: Sign Artifacts to main release channel
       - name: Sign Artifacts to main release channel
         if: github.ref == 'refs/heads/main' && env.GHCR_USERNAME != ''
         if: github.ref == 'refs/heads/main' && env.GHCR_USERNAME != ''

+ 2 - 2
.github/workflows/e2e.yml

@@ -8,7 +8,7 @@ env:
   # Common versions
   # Common versions
   GO_VERSION: '1.17'
   GO_VERSION: '1.17'
   GOLANGCI_VERSION: 'v1.33'
   GOLANGCI_VERSION: 'v1.33'
-  GINKGO_VERSION: 'v2.1.3'
+  GINKGO_VERSION: 'v2.1.4'
   DOCKER_BUILDX_VERSION: 'v0.4.2'
   DOCKER_BUILDX_VERSION: 'v0.4.2'
   KIND_VERSION: 'v0.11.1'
   KIND_VERSION: 'v0.11.1'
   KIND_IMAGE: 'kindest/node:v1.23.3'
   KIND_IMAGE: 'kindest/node:v1.23.3'
@@ -35,7 +35,7 @@ jobs:
   # Branch-based pull request
   # Branch-based pull request
   integration-trusted:
   integration-trusted:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
-    if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
+    if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && github.actor !='dependabot[bot]'
     steps:
     steps:
 
 
     - name: Branch based PR checkout
     - name: Branch based PR checkout

+ 2 - 2
.github/workflows/helm.yml

@@ -26,7 +26,7 @@ jobs:
           make helm.generate
           make helm.generate
 
 
       - name: Set up Helm
       - name: Set up Helm
-        uses: azure/setup-helm@v3.1
+        uses: azure/setup-helm@v3.3
         with:
         with:
           version: v3.4.2
           version: v3.4.2
 
 
@@ -62,7 +62,7 @@ jobs:
           git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
           git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
 
 
       - name: Set up Helm
       - name: Set up Helm
-        uses: azure/setup-helm@v3.1
+        uses: azure/setup-helm@v3.3
         with:
         with:
           version: v3.4.2
           version: v3.4.2
 
 

+ 1 - 1
.github/workflows/release.yml

@@ -126,7 +126,7 @@ jobs:
 
 
       - name: Install cosign
       - name: Install cosign
         if: env.GHCR_USERNAME != ''
         if: env.GHCR_USERNAME != ''
-        uses: sigstore/cosign-installer@v2.4.1
+        uses: sigstore/cosign-installer@v2.5.0
 
 
       - name: Sign Container Image
       - name: Sign Container Image
         if: env.GHCR_USERNAME != ''
         if: env.GHCR_USERNAME != ''

+ 1 - 1
Dockerfile.standalone

@@ -1,5 +1,5 @@
 # This version of Dockerfile is for building without external dependencies.
 # This version of Dockerfile is for building without external dependencies.
-FROM golang:1.18-alpine AS builder
+FROM golang:1.19.0-alpine AS builder
 ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64
 ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64
 WORKDIR /app
 WORKDIR /app
 # Avoid invalidating the `go mod download` cache when only code has changed.
 # Avoid invalidating the `go mod download` cache when only code has changed.

+ 3 - 37
Makefile

@@ -17,7 +17,7 @@ all: $(addprefix build-,$(ARCH))
 export IMAGE_REGISTRY ?= ghcr.io/external-secrets/external-secrets
 export IMAGE_REGISTRY ?= ghcr.io/external-secrets/external-secrets
 
 
 #Valid licenses for license.check
 #Valid licenses for license.check
-LICENSES ?= Apache-2.0|MIT|BSD-3-Clause|ISC|MPL-2.0|BSD-2-Clause|Unknown
+LICENSES ?= Apache-2.0|MIT|BSD-3-Clause|ISC|MPL-2.0|BSD-2-Clause
 BUNDLE_DIR     ?= deploy/crds
 BUNDLE_DIR     ?= deploy/crds
 CRD_DIR     ?= config/crds
 CRD_DIR     ?= config/crds
 
 
@@ -145,15 +145,7 @@ fmt: lint.check ## Ensure consistent code style
 	@$(OK) Ensured consistent code style
 	@$(OK) Ensured consistent code style
 
 
 generate: ## Generate code and crds
 generate: ## Generate code and crds
-	@go run sigs.k8s.io/controller-tools/cmd/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
-	@go run sigs.k8s.io/controller-tools/cmd/controller-gen crd paths="./..." output:crd:artifacts:config=$(CRD_DIR)/bases
-# Remove extra header lines in generated CRDs
-	@for i in $(CRD_DIR)/bases/*.yaml; do \
-  		tail -n +2 <"$$i" >"$$i.bkp" && \
-  		cp "$$i.bkp" "$$i" && \
-  		rm "$$i.bkp"; \
-  	done
-	@yq e '.spec.conversion.strategy = "Webhook" | .spec.conversion.webhook.conversionReviewVersions = ["v1"] | .spec.conversion.webhook.clientConfig.service.name = "kubernetes" | .spec.conversion.webhook.clientConfig.service.namespace = "default" |	.spec.conversion.webhook.clientConfig.service.path = "/convert"' $(CRD_DIR)/bases/*  > $(BUNDLE_DIR)/bundle.yaml
+	@./hack/crd.generate.sh $(BUNDLE_DIR) $(CRD_DIR)
 	@$(OK) Finished generating deepcopy and crds
 	@$(OK) Finished generating deepcopy and crds
 
 
 # ====================================================================================
 # ====================================================================================
@@ -190,33 +182,7 @@ helm.build: helm.generate ## Build helm chart
 	@$(OK) helm package
 	@$(OK) helm package
 
 
 helm.generate:
 helm.generate:
-# Split the generated bundle yaml file to inject control flags
-	@for i in $(BUNDLE_DIR)/*.yaml; do \
-		yq e -Ns '"$(HELM_DIR)/templates/crds/" + .spec.names.singular' "$$i"; \
-	done
-# Add helm if statement for controlling the install of CRDs
-	@for i in $(HELM_DIR)/templates/crds/*.yml; do \
-		export CRDS_FLAG_NAME="create$$(yq e '.spec.names.kind' $$i)"; \
-		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"; \
-		else \
-			echo "{{- if .Values.installCRDs }}" > "$$i"; \
-		fi; \
-		cat "$$i.bkp" >> "$$i" && \
-		echo "{{- end }}" >> "$$i" && \
-		rm "$$i.bkp" && \
-		if [[ "$$OSTYPE" == "darwin"* ]]; then \
-		  SEDPRG="gsed"; \
-		else \
-		  SEDPRG="sed"; \
-		fi; \
-		$$SEDPRG -i 's/name: kubernetes/name: {{ include "external-secrets.fullname" . }}-webhook/g' "$$i" && \
-		$$SEDPRG -i 's/namespace: default/namespace: {{ .Release.Namespace | quote }}/g' "$$i" && \
-		mv "$$i" "$${i%.yml}.yaml"; \
-	done
+	./hack/helm.generate.sh $(BUNDLE_DIR) $(HELM_DIR)
 	@$(OK) Finished generating helm chart files
 	@$(OK) Finished generating helm chart files
 
 
 # ====================================================================================
 # ====================================================================================

+ 1 - 1
apis/externalsecrets/v1alpha1/secretstore_azurekv_types.go

@@ -27,7 +27,7 @@ const (
 	// Using service principal to authenticate, which needs a tenantId, a clientId and a clientSecret.
 	// Using service principal to authenticate, which needs a tenantId, a clientId and a clientSecret.
 	AzureServicePrincipal AzureAuthType = "ServicePrincipal"
 	AzureServicePrincipal AzureAuthType = "ServicePrincipal"
 
 
-	// Using Managed Identity to authenticate. Used with aad-pod-identity installed in the clister.
+	// Using Managed Identity to authenticate. Used with aad-pod-identity installed in the cluster.
 	AzureManagedIdentity AzureAuthType = "ManagedIdentity"
 	AzureManagedIdentity AzureAuthType = "ManagedIdentity"
 
 
 	// Using Workload Identity service accounts to authenticate.
 	// Using Workload Identity service accounts to authenticate.

+ 22 - 4
apis/externalsecrets/v1beta1/externalsecret_types.go

@@ -184,7 +184,7 @@ type ExternalSecretDataRemoteRef struct {
 	ConversionStrategy ExternalSecretConversionStrategy `json:"conversionStrategy,omitempty"`
 	ConversionStrategy ExternalSecretConversionStrategy `json:"conversionStrategy,omitempty"`
 
 
 	// +optional
 	// +optional
-	// Used to define a conversion Strategy
+	// Used to define a decoding Strategy
 	// +kubebuilder:default="None"
 	// +kubebuilder:default="None"
 	DecodingStrategy ExternalSecretDecodingStrategy `json:"decodingStrategy,omitempty"`
 	DecodingStrategy ExternalSecretDecodingStrategy `json:"decodingStrategy,omitempty"`
 }
 }
@@ -212,8 +212,6 @@ const (
 	ExternalSecretDecodeNone      ExternalSecretDecodingStrategy = "None"
 	ExternalSecretDecodeNone      ExternalSecretDecodingStrategy = "None"
 )
 )
 
 
-// +kubebuilder:validation:MinProperties=1
-// +kubebuilder:validation:MaxProperties=1
 type ExternalSecretDataFromRemoteRef struct {
 type ExternalSecretDataFromRemoteRef struct {
 	// Used to extract multiple key/value pairs from one secret
 	// Used to extract multiple key/value pairs from one secret
 	// +optional
 	// +optional
@@ -221,8 +219,26 @@ type ExternalSecretDataFromRemoteRef struct {
 	// Used to find secrets based on tags or regular expressions
 	// Used to find secrets based on tags or regular expressions
 	// +optional
 	// +optional
 	Find *ExternalSecretFind `json:"find,omitempty"`
 	Find *ExternalSecretFind `json:"find,omitempty"`
+
+	// Used to rewrite secret Keys after getting them from the secret Provider
+	// Multiple Rewrite operations can be provided. They are applied in a layered order (first to last)
+	// +optional
+	Rewrite []ExternalSecretRewrite `json:"rewrite,omitempty"`
 }
 }
 
 
+type ExternalSecretRewrite struct {
+	// Used to rewrite with regular expressions.
+	// The resulting key will be the output of a regexp.ReplaceAll operation.
+	// +optional
+	Regexp *ExternalSecretRewriteRegexp `json:"regexp,omitempty"`
+}
+
+type ExternalSecretRewriteRegexp struct {
+	// Used to define the regular expression of a re.Compiler.
+	Source string `json:"source"`
+	// Used to define the target pattern of a ReplaceAll operation.
+	Target string `json:"target"`
+}
 type ExternalSecretFind struct {
 type ExternalSecretFind struct {
 	// A root path to start the find operations.
 	// A root path to start the find operations.
 	// +optional
 	// +optional
@@ -241,7 +257,7 @@ type ExternalSecretFind struct {
 	ConversionStrategy ExternalSecretConversionStrategy `json:"conversionStrategy,omitempty"`
 	ConversionStrategy ExternalSecretConversionStrategy `json:"conversionStrategy,omitempty"`
 
 
 	// +optional
 	// +optional
-	// Used to define a conversion Strategy
+	// Used to define a decoding Strategy
 	// +kubebuilder:default="None"
 	// +kubebuilder:default="None"
 	DecodingStrategy ExternalSecretDecodingStrategy `json:"decodingStrategy,omitempty"`
 	DecodingStrategy ExternalSecretDecodingStrategy `json:"decodingStrategy,omitempty"`
 }
 }
@@ -255,6 +271,7 @@ type FindName struct {
 // ExternalSecretSpec defines the desired state of ExternalSecret.
 // ExternalSecretSpec defines the desired state of ExternalSecret.
 type ExternalSecretSpec struct {
 type ExternalSecretSpec struct {
 	SecretStoreRef SecretStoreRef `json:"secretStoreRef"`
 	SecretStoreRef SecretStoreRef `json:"secretStoreRef"`
+	// +kubebuilder:default={creationPolicy:Owner,deletionPolicy:Retain}
 	// +optional
 	// +optional
 	Target ExternalSecretTarget `json:"target,omitempty"`
 	Target ExternalSecretTarget `json:"target,omitempty"`
 
 
@@ -307,6 +324,7 @@ const (
 	ReasonUnavailableStore     = "UnavailableStore"
 	ReasonUnavailableStore     = "UnavailableStore"
 	ReasonProviderClientConfig = "InvalidProviderClientConfig"
 	ReasonProviderClientConfig = "InvalidProviderClientConfig"
 	ReasonUpdateFailed         = "UpdateFailed"
 	ReasonUpdateFailed         = "UpdateFailed"
+	ReasonDeprecated           = "ParameterDeprecated"
 	ReasonUpdated              = "Updated"
 	ReasonUpdated              = "Updated"
 	ReasonDeleted              = "Deleted"
 	ReasonDeleted              = "Deleted"
 )
 )

+ 1 - 1
apis/externalsecrets/v1beta1/secretstore_azurekv_types.go

@@ -27,7 +27,7 @@ const (
 	// Using service principal to authenticate, which needs a tenantId, a clientId and a clientSecret.
 	// Using service principal to authenticate, which needs a tenantId, a clientId and a clientSecret.
 	AzureServicePrincipal AzureAuthType = "ServicePrincipal"
 	AzureServicePrincipal AzureAuthType = "ServicePrincipal"
 
 
-	// Using Managed Identity to authenticate. Used with aad-pod-identity installed in the clister.
+	// Using Managed Identity to authenticate. Used with aad-pod-identity installed in the cluster.
 	AzureManagedIdentity AzureAuthType = "ManagedIdentity"
 	AzureManagedIdentity AzureAuthType = "ManagedIdentity"
 
 
 	// Using Workload Identity service accounts to authenticate.
 	// Using Workload Identity service accounts to authenticate.

+ 15 - 2
apis/externalsecrets/v1beta1/secretstore_ibm_types.go

@@ -28,12 +28,25 @@ type IBMProvider struct {
 	ServiceURL *string `json:"serviceUrl,omitempty"`
 	ServiceURL *string `json:"serviceUrl,omitempty"`
 }
 }
 
 
+// +kubebuilder:validation:MinProperties=1
+// +kubebuilder:validation:MaxProperties=1
 type IBMAuth struct {
 type IBMAuth struct {
-	SecretRef IBMAuthSecretRef `json:"secretRef"`
+	SecretRef     IBMAuthSecretRef     `json:"secretRef,omitempty"`
+	ContainerAuth IBMAuthContainerAuth `json:"containerAuth,omitempty"`
 }
 }
 
 
 type IBMAuthSecretRef struct {
 type IBMAuthSecretRef struct {
 	// The SecretAccessKey is used for authentication
 	// The SecretAccessKey is used for authentication
-	// +optional
 	SecretAPIKey esmeta.SecretKeySelector `json:"secretApiKeySecretRef,omitempty"`
 	SecretAPIKey esmeta.SecretKeySelector `json:"secretApiKeySecretRef,omitempty"`
 }
 }
+
+// IBM Container-based auth with IAM Trusted Profile.
+type IBMAuthContainerAuth struct {
+	// the IBM Trusted Profile
+	Profile string `json:"profile"`
+
+	// Location the token is mounted on the pod
+	TokenLocation string `json:"tokenLocation,omitempty"`
+
+	IAMEndpoint string `json:"iamEndpoint,omitempty"`
+}

+ 28 - 0
apis/externalsecrets/v1beta1/secretstore_types.go

@@ -107,6 +107,34 @@ type SecretStoreProvider struct {
 	Senhasegura *SenhaseguraProvider `json:"senhasegura,omitempty"`
 	Senhasegura *SenhaseguraProvider `json:"senhasegura,omitempty"`
 }
 }
 
 
+type CAProviderType string
+
+const (
+	CAProviderTypeSecret    CAProviderType = "Secret"
+	CAProviderTypeConfigMap CAProviderType = "ConfigMap"
+)
+
+// Used to provide custom certificate authority (CA) certificates
+// for a secret store. The CAProvider points to a Secret or ConfigMap resource
+// that contains a PEM-encoded certificate.
+type CAProvider struct {
+	// The type of provider to use such as "Secret", or "ConfigMap".
+	// +kubebuilder:validation:Enum="Secret";"ConfigMap"
+	Type CAProviderType `json:"type"`
+
+	// The name of the object located at the provider type.
+	Name string `json:"name"`
+
+	// The key where the CA certificate can be found in the Secret or ConfigMap.
+	// +kubebuilder:validation:Optional
+	Key string `json:"key,omitempty"`
+
+	// The namespace the Provider type is in.
+	// Can only be defined when used in a ClusterSecretStore.
+	// +optional
+	Namespace *string `json:"namespace,omitempty"`
+}
+
 type SecretStoreRetrySettings struct {
 type SecretStoreRetrySettings struct {
 	MaxRetries    *int32  `json:"maxRetries,omitempty"`
 	MaxRetries    *int32  `json:"maxRetries,omitempty"`
 	RetryInterval *string `json:"retryInterval,omitempty"`
 	RetryInterval *string `json:"retryInterval,omitempty"`

+ 0 - 25
apis/externalsecrets/v1beta1/secretstore_vault_types.go

@@ -25,31 +25,6 @@ const (
 	VaultKVStoreV2 VaultKVStoreVersion = "v2"
 	VaultKVStoreV2 VaultKVStoreVersion = "v2"
 )
 )
 
 
-type CAProviderType string
-
-const (
-	CAProviderTypeSecret    CAProviderType = "Secret"
-	CAProviderTypeConfigMap CAProviderType = "ConfigMap"
-)
-
-// Defines a location to fetch the cert for the vault provider from.
-type CAProvider struct {
-	// The type of provider to use such as "Secret", or "ConfigMap".
-	// +kubebuilder:validation:Enum="Secret";"ConfigMap"
-	Type CAProviderType `json:"type"`
-
-	// The name of the object located at the provider type.
-	Name string `json:"name"`
-
-	// The key the value inside of the provider type to use, only used with "Secret" type
-	// +kubebuilder:validation:Optional
-	Key string `json:"key,omitempty"`
-
-	// The namespace the Provider type is in.
-	// +optional
-	Namespace *string `json:"namespace,omitempty"`
-}
-
 // Configures an store to sync secrets using a HashiCorp Vault
 // Configures an store to sync secrets using a HashiCorp Vault
 // KV backend.
 // KV backend.
 type VaultProvider struct {
 type VaultProvider struct {

+ 58 - 0
apis/externalsecrets/v1beta1/zz_generated.deepcopy.go

@@ -578,6 +578,13 @@ func (in *ExternalSecretDataFromRemoteRef) DeepCopyInto(out *ExternalSecretDataF
 		*out = new(ExternalSecretFind)
 		*out = new(ExternalSecretFind)
 		(*in).DeepCopyInto(*out)
 		(*in).DeepCopyInto(*out)
 	}
 	}
+	if in.Rewrite != nil {
+		in, out := &in.Rewrite, &out.Rewrite
+		*out = make([]ExternalSecretRewrite, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
 }
 }
 
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSecretDataFromRemoteRef.
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSecretDataFromRemoteRef.
@@ -669,6 +676,41 @@ func (in *ExternalSecretList) DeepCopyObject() runtime.Object {
 	return nil
 	return nil
 }
 }
 
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ExternalSecretRewrite) DeepCopyInto(out *ExternalSecretRewrite) {
+	*out = *in
+	if in.Regexp != nil {
+		in, out := &in.Regexp, &out.Regexp
+		*out = new(ExternalSecretRewriteRegexp)
+		**out = **in
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSecretRewrite.
+func (in *ExternalSecretRewrite) DeepCopy() *ExternalSecretRewrite {
+	if in == nil {
+		return nil
+	}
+	out := new(ExternalSecretRewrite)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ExternalSecretRewriteRegexp) DeepCopyInto(out *ExternalSecretRewriteRegexp) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSecretRewriteRegexp.
+func (in *ExternalSecretRewriteRegexp) DeepCopy() *ExternalSecretRewriteRegexp {
+	if in == nil {
+		return nil
+	}
+	out := new(ExternalSecretRewriteRegexp)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *ExternalSecretSpec) DeepCopyInto(out *ExternalSecretSpec) {
 func (in *ExternalSecretSpec) DeepCopyInto(out *ExternalSecretSpec) {
 	*out = *in
 	*out = *in
@@ -1035,6 +1077,7 @@ func (in *GitlabSecretRef) DeepCopy() *GitlabSecretRef {
 func (in *IBMAuth) DeepCopyInto(out *IBMAuth) {
 func (in *IBMAuth) DeepCopyInto(out *IBMAuth) {
 	*out = *in
 	*out = *in
 	in.SecretRef.DeepCopyInto(&out.SecretRef)
 	in.SecretRef.DeepCopyInto(&out.SecretRef)
+	out.ContainerAuth = in.ContainerAuth
 }
 }
 
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMAuth.
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMAuth.
@@ -1047,6 +1090,21 @@ func (in *IBMAuth) DeepCopy() *IBMAuth {
 	return out
 	return out
 }
 }
 
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *IBMAuthContainerAuth) DeepCopyInto(out *IBMAuthContainerAuth) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMAuthContainerAuth.
+func (in *IBMAuthContainerAuth) DeepCopy() *IBMAuthContainerAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(IBMAuthContainerAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *IBMAuthSecretRef) DeepCopyInto(out *IBMAuthSecretRef) {
 func (in *IBMAuthSecretRef) DeepCopyInto(out *IBMAuthSecretRef) {
 	*out = *in
 	*out = *in

+ 32 - 18
cmd/root.go

@@ -51,8 +51,12 @@ var (
 	healthzAddr                           string
 	healthzAddr                           string
 	controllerClass                       string
 	controllerClass                       string
 	enableLeaderElection                  bool
 	enableLeaderElection                  bool
+	enableSecretsCache                    bool
+	enableConfigMapsCache                 bool
 	concurrent                            int
 	concurrent                            int
 	port                                  int
 	port                                  int
+	clientQPS                             float32
+	clientBurst                           int
 	loglevel                              string
 	loglevel                              string
 	namespace                             string
 	namespace                             string
 	enableClusterStoreReconciler          bool
 	enableClusterStoreReconciler          bool
@@ -85,6 +89,19 @@ var rootCmd = &cobra.Command{
 	Long:  `For more information visit https://external-secrets.io`,
 	Long:  `For more information visit https://external-secrets.io`,
 	Run: func(cmd *cobra.Command, args []string) {
 	Run: func(cmd *cobra.Command, args []string) {
 		var lvl zapcore.Level
 		var lvl zapcore.Level
+		// the client creates a ListWatch for all resource kinds that
+		// are requested with .Get().
+		// We want to avoid to cache all secrets or configmaps in memory.
+		// The ES controller uses v1.PartialObjectMetadata for the secrets
+		// that he owns.
+		// see #721
+		cacheList := make([]client.Object, 0)
+		if !enableSecretsCache {
+			cacheList = append(cacheList, &v1.Secret{})
+		}
+		if !enableConfigMapsCache {
+			cacheList = append(cacheList, &v1.ConfigMap{})
+		}
 		err := lvl.UnmarshalText([]byte(loglevel))
 		err := lvl.UnmarshalText([]byte(loglevel))
 		if err != nil {
 		if err != nil {
 			setupLog.Error(err, "error unmarshalling loglevel")
 			setupLog.Error(err, "error unmarshalling loglevel")
@@ -92,24 +109,17 @@ var rootCmd = &cobra.Command{
 		}
 		}
 		logger := zap.New(zap.Level(lvl))
 		logger := zap.New(zap.Level(lvl))
 		ctrl.SetLogger(logger)
 		ctrl.SetLogger(logger)
-
-		mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
-			Scheme:             scheme,
-			MetricsBindAddress: metricsAddr,
-			Port:               9443,
-			LeaderElection:     enableLeaderElection,
-			LeaderElectionID:   "external-secrets-controller",
-			ClientDisableCacheFor: []client.Object{
-				// the client creates a ListWatch for all resource kinds that
-				// are requested with .Get().
-				// We want to avoid to cache all secrets or configmaps in memory.
-				// The ES controller uses v1.PartialObjectMetadata for the secrets
-				// that he owns.
-				// see #721
-				&v1.Secret{},
-				&v1.ConfigMap{},
-			},
-			Namespace: namespace,
+		config := ctrl.GetConfigOrDie()
+		config.QPS = clientQPS
+		config.Burst = clientBurst
+		mgr, err := ctrl.NewManager(config, ctrl.Options{
+			Scheme:                scheme,
+			MetricsBindAddress:    metricsAddr,
+			Port:                  9443,
+			LeaderElection:        enableLeaderElection,
+			LeaderElectionID:      "external-secrets-controller",
+			ClientDisableCacheFor: cacheList,
+			Namespace:             namespace,
 		})
 		})
 		if err != nil {
 		if err != nil {
 			setupLog.Error(err, "unable to start manager")
 			setupLog.Error(err, "unable to start manager")
@@ -199,11 +209,15 @@ func init() {
 		"Enable leader election for controller manager. "+
 		"Enable leader election for controller manager. "+
 			"Enabling this will ensure there is only one active controller manager.")
 			"Enabling this will ensure there is only one active controller manager.")
 	rootCmd.Flags().IntVar(&concurrent, "concurrent", 1, "The number of concurrent ExternalSecret reconciles.")
 	rootCmd.Flags().IntVar(&concurrent, "concurrent", 1, "The number of concurrent ExternalSecret reconciles.")
+	rootCmd.Flags().Float32Var(&clientQPS, "client-qps", 0, "QPS configuration to be passed to rest.Client")
+	rootCmd.Flags().IntVar(&clientBurst, "client-burst", 0, "Maximum Burst allowed to be passed to rest.Client")
 	rootCmd.Flags().StringVar(&loglevel, "loglevel", "info", "loglevel to use, one of: debug, info, warn, error, dpanic, panic, fatal")
 	rootCmd.Flags().StringVar(&loglevel, "loglevel", "info", "loglevel to use, one of: debug, info, warn, error, dpanic, panic, fatal")
 	rootCmd.Flags().StringVar(&namespace, "namespace", "", "watch external secrets scoped in the provided namespace only. ClusterSecretStore can be used but only work if it doesn't reference resources from other namespaces")
 	rootCmd.Flags().StringVar(&namespace, "namespace", "", "watch external secrets scoped in the provided namespace only. ClusterSecretStore can be used but only work if it doesn't reference resources from other namespaces")
 	rootCmd.Flags().BoolVar(&enableClusterStoreReconciler, "enable-cluster-store-reconciler", true, "Enable cluster store reconciler.")
 	rootCmd.Flags().BoolVar(&enableClusterStoreReconciler, "enable-cluster-store-reconciler", true, "Enable cluster store reconciler.")
 	rootCmd.Flags().BoolVar(&enableClusterExternalSecretReconciler, "enable-cluster-external-secret-reconciler", true, "Enable cluster external secret reconciler.")
 	rootCmd.Flags().BoolVar(&enableClusterExternalSecretReconciler, "enable-cluster-external-secret-reconciler", true, "Enable cluster external secret reconciler.")
 	rootCmd.Flags().BoolVar(&enablePushSecretReconciler, "experimental-enable-push-secret-reconciler", false, "Enable push secret reconciler.")
 	rootCmd.Flags().BoolVar(&enablePushSecretReconciler, "experimental-enable-push-secret-reconciler", false, "Enable push secret reconciler.")
+	rootCmd.Flags().BoolVar(&enableSecretsCache, "enable-secrets-caching", false, "Enable secrets caching for external-secrets pod.")
+	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().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(&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(&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.")

+ 34 - 6
config/crds/bases/external-secrets.io_clusterexternalsecrets.yaml

@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 kind: CustomResourceDefinition
 metadata:
 metadata:
   annotations:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.9.0
+    controller-gen.kubebuilder.io/version: v0.9.2
   creationTimestamp: null
   creationTimestamp: null
   name: clusterexternalsecrets.external-secrets.io
   name: clusterexternalsecrets.external-secrets.io
 spec:
 spec:
@@ -77,7 +77,7 @@ spec:
                               type: string
                               type: string
                             decodingStrategy:
                             decodingStrategy:
                               default: None
                               default: None
-                              description: Used to define a conversion Strategy
+                              description: Used to define a decoding Strategy
                               type: string
                               type: string
                             key:
                             key:
                               description: Key is the key used in the Provider, mandatory
                               description: Key is the key used in the Provider, mandatory
@@ -110,8 +110,6 @@ spec:
                       Provider data If multiple entries are specified, the Secret
                       Provider data If multiple entries are specified, the Secret
                       keys are merged in the specified order
                       keys are merged in the specified order
                     items:
                     items:
-                      maxProperties: 1
-                      minProperties: 1
                       properties:
                       properties:
                         extract:
                         extract:
                           description: Used to extract multiple key/value pairs from
                           description: Used to extract multiple key/value pairs from
@@ -123,7 +121,7 @@ spec:
                               type: string
                               type: string
                             decodingStrategy:
                             decodingStrategy:
                               default: None
                               default: None
-                              description: Used to define a conversion Strategy
+                              description: Used to define a decoding Strategy
                               type: string
                               type: string
                             key:
                             key:
                               description: Key is the key used in the Provider, mandatory
                               description: Key is the key used in the Provider, mandatory
@@ -154,7 +152,7 @@ spec:
                               type: string
                               type: string
                             decodingStrategy:
                             decodingStrategy:
                               default: None
                               default: None
-                              description: Used to define a conversion Strategy
+                              description: Used to define a decoding Strategy
                               type: string
                               type: string
                             name:
                             name:
                               description: Finds secrets based on the name.
                               description: Finds secrets based on the name.
@@ -172,6 +170,32 @@ spec:
                               description: Find secrets based on tags.
                               description: Find secrets based on tags.
                               type: object
                               type: object
                           type: object
                           type: object
+                        rewrite:
+                          description: Used to rewrite secret Keys after getting them
+                            from the secret Provider Multiple Rewrite operations can
+                            be provided. They are applied in a layered order (first
+                            to last)
+                          items:
+                            properties:
+                              regexp:
+                                description: Used to rewrite with regular expressions.
+                                  The resulting key will be the output of a regexp.ReplaceAll
+                                  operation.
+                                properties:
+                                  source:
+                                    description: Used to define the regular expression
+                                      of a re.Compiler.
+                                    type: string
+                                  target:
+                                    description: Used to define the target pattern
+                                      of a ReplaceAll operation.
+                                    type: string
+                                required:
+                                - source
+                                - target
+                                type: object
+                            type: object
+                          type: array
                       type: object
                       type: object
                     type: array
                     type: array
                   refreshInterval:
                   refreshInterval:
@@ -196,6 +220,9 @@ spec:
                     - name
                     - name
                     type: object
                     type: object
                   target:
                   target:
+                    default:
+                      creationPolicy: Owner
+                      deletionPolicy: Retain
                     description: ExternalSecretTarget defines the Kubernetes Secret
                     description: ExternalSecretTarget defines the Kubernetes Secret
                       to be created There can be only one target per ExternalSecret.
                       to be created There can be only one target per ExternalSecret.
                     properties:
                     properties:
@@ -344,6 +371,7 @@ spec:
                       are ANDed.
                       are ANDed.
                     type: object
                     type: object
                 type: object
                 type: object
+                x-kubernetes-map-type: atomic
               refreshTime:
               refreshTime:
                 description: The time in which the controller should reconcile it's
                 description: The time in which the controller should reconcile it's
                   objects and recheck namespaces for labels.
                   objects and recheck namespaces for labels.

+ 26 - 8
config/crds/bases/external-secrets.io_clustersecretstores.yaml

@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 kind: CustomResourceDefinition
 metadata:
 metadata:
   annotations:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.9.0
+    controller-gen.kubebuilder.io/version: v0.9.2
   creationTimestamp: null
   creationTimestamp: null
   name: clustersecretstores.external-secrets.io
   name: clustersecretstores.external-secrets.io
 spec:
 spec:
@@ -1907,7 +1907,25 @@ spec:
                       auth:
                       auth:
                         description: Auth configures how secret-manager authenticates
                         description: Auth configures how secret-manager authenticates
                           with the IBM secrets manager.
                           with the IBM secrets manager.
+                        maxProperties: 1
+                        minProperties: 1
                         properties:
                         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:
                           secretRef:
                             properties:
                             properties:
                               secretApiKeySecretRef:
                               secretApiKeySecretRef:
@@ -1931,8 +1949,6 @@ spec:
                                     type: string
                                     type: string
                                 type: object
                                 type: object
                             type: object
                             type: object
-                        required:
-                        - secretRef
                         type: object
                         type: object
                       serviceUrl:
                       serviceUrl:
                         description: ServiceURL is the Endpoint URL that is specific
                         description: ServiceURL is the Endpoint URL that is specific
@@ -2057,8 +2073,8 @@ spec:
                             description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider'
                             description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider'
                             properties:
                             properties:
                               key:
                               key:
-                                description: The key the value inside of the provider
-                                  type to use, only used with "Secret" type
+                                description: The key where the CA certificate can
+                                  be found in the Secret or ConfigMap.
                                 type: string
                                 type: string
                               name:
                               name:
                                 description: The name of the object located at the
                                 description: The name of the object located at the
@@ -2066,6 +2082,7 @@ spec:
                                 type: string
                                 type: string
                               namespace:
                               namespace:
                                 description: The namespace the Provider type is in.
                                 description: The namespace the Provider type is in.
+                                  Can only be defined when used in a ClusterSecretStore.
                                 type: string
                                 type: string
                               type:
                               type:
                                 description: The type of provider to use such as "Secret",
                                 description: The type of provider to use such as "Secret",
@@ -2590,15 +2607,16 @@ spec:
                           Vault server certificate.
                           Vault server certificate.
                         properties:
                         properties:
                           key:
                           key:
-                            description: The key the value inside of the provider
-                              type to use, only used with "Secret" type
+                            description: The key where the CA certificate can be found
+                              in the Secret or ConfigMap.
                             type: string
                             type: string
                           name:
                           name:
                             description: The name of the object located at the provider
                             description: The name of the object located at the provider
                               type.
                               type.
                             type: string
                             type: string
                           namespace:
                           namespace:
-                            description: The namespace the Provider type is in.
+                            description: The namespace the Provider type is in. Can
+                              only be defined when used in a ClusterSecretStore.
                             type: string
                             type: string
                           type:
                           type:
                             description: The type of provider to use such as "Secret",
                             description: The type of provider to use such as "Secret",

+ 32 - 6
config/crds/bases/external-secrets.io_externalsecrets.yaml

@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 kind: CustomResourceDefinition
 metadata:
 metadata:
   annotations:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.9.0
+    controller-gen.kubebuilder.io/version: v0.9.2
   creationTimestamp: null
   creationTimestamp: null
   name: externalsecrets.external-secrets.io
   name: externalsecrets.external-secrets.io
 spec:
 spec:
@@ -312,7 +312,7 @@ spec:
                           type: string
                           type: string
                         decodingStrategy:
                         decodingStrategy:
                           default: None
                           default: None
-                          description: Used to define a conversion Strategy
+                          description: Used to define a decoding Strategy
                           type: string
                           type: string
                         key:
                         key:
                           description: Key is the key used in the Provider, mandatory
                           description: Key is the key used in the Provider, mandatory
@@ -345,8 +345,6 @@ spec:
                   Provider data If multiple entries are specified, the Secret keys
                   Provider data If multiple entries are specified, the Secret keys
                   are merged in the specified order
                   are merged in the specified order
                 items:
                 items:
-                  maxProperties: 1
-                  minProperties: 1
                   properties:
                   properties:
                     extract:
                     extract:
                       description: Used to extract multiple key/value pairs from one
                       description: Used to extract multiple key/value pairs from one
@@ -358,7 +356,7 @@ spec:
                           type: string
                           type: string
                         decodingStrategy:
                         decodingStrategy:
                           default: None
                           default: None
-                          description: Used to define a conversion Strategy
+                          description: Used to define a decoding Strategy
                           type: string
                           type: string
                         key:
                         key:
                           description: Key is the key used in the Provider, mandatory
                           description: Key is the key used in the Provider, mandatory
@@ -388,7 +386,7 @@ spec:
                           type: string
                           type: string
                         decodingStrategy:
                         decodingStrategy:
                           default: None
                           default: None
-                          description: Used to define a conversion Strategy
+                          description: Used to define a decoding Strategy
                           type: string
                           type: string
                         name:
                         name:
                           description: Finds secrets based on the name.
                           description: Finds secrets based on the name.
@@ -406,6 +404,31 @@ spec:
                           description: Find secrets based on tags.
                           description: Find secrets based on tags.
                           type: object
                           type: object
                       type: object
                       type: object
+                    rewrite:
+                      description: Used to rewrite secret Keys after getting them
+                        from the secret Provider Multiple Rewrite operations can be
+                        provided. They are applied in a layered order (first to last)
+                      items:
+                        properties:
+                          regexp:
+                            description: Used to rewrite with regular expressions.
+                              The resulting key will be the output of a regexp.ReplaceAll
+                              operation.
+                            properties:
+                              source:
+                                description: Used to define the regular expression
+                                  of a re.Compiler.
+                                type: string
+                              target:
+                                description: Used to define the target pattern of
+                                  a ReplaceAll operation.
+                                type: string
+                            required:
+                            - source
+                            - target
+                            type: object
+                        type: object
+                      type: array
                   type: object
                   type: object
                 type: array
                 type: array
               refreshInterval:
               refreshInterval:
@@ -430,6 +453,9 @@ spec:
                 - name
                 - name
                 type: object
                 type: object
               target:
               target:
+                default:
+                  creationPolicy: Owner
+                  deletionPolicy: Retain
                 description: ExternalSecretTarget defines the Kubernetes Secret to
                 description: ExternalSecretTarget defines the Kubernetes Secret to
                   be created There can be only one target per ExternalSecret.
                   be created There can be only one target per ExternalSecret.
                 properties:
                 properties:

+ 26 - 8
config/crds/bases/external-secrets.io_secretstores.yaml

@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 kind: CustomResourceDefinition
 metadata:
 metadata:
   annotations:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.9.0
+    controller-gen.kubebuilder.io/version: v0.9.2
   creationTimestamp: null
   creationTimestamp: null
   name: secretstores.external-secrets.io
   name: secretstores.external-secrets.io
 spec:
 spec:
@@ -1907,7 +1907,25 @@ spec:
                       auth:
                       auth:
                         description: Auth configures how secret-manager authenticates
                         description: Auth configures how secret-manager authenticates
                           with the IBM secrets manager.
                           with the IBM secrets manager.
+                        maxProperties: 1
+                        minProperties: 1
                         properties:
                         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:
                           secretRef:
                             properties:
                             properties:
                               secretApiKeySecretRef:
                               secretApiKeySecretRef:
@@ -1931,8 +1949,6 @@ spec:
                                     type: string
                                     type: string
                                 type: object
                                 type: object
                             type: object
                             type: object
-                        required:
-                        - secretRef
                         type: object
                         type: object
                       serviceUrl:
                       serviceUrl:
                         description: ServiceURL is the Endpoint URL that is specific
                         description: ServiceURL is the Endpoint URL that is specific
@@ -2057,8 +2073,8 @@ spec:
                             description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider'
                             description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider'
                             properties:
                             properties:
                               key:
                               key:
-                                description: The key the value inside of the provider
-                                  type to use, only used with "Secret" type
+                                description: The key where the CA certificate can
+                                  be found in the Secret or ConfigMap.
                                 type: string
                                 type: string
                               name:
                               name:
                                 description: The name of the object located at the
                                 description: The name of the object located at the
@@ -2066,6 +2082,7 @@ spec:
                                 type: string
                                 type: string
                               namespace:
                               namespace:
                                 description: The namespace the Provider type is in.
                                 description: The namespace the Provider type is in.
+                                  Can only be defined when used in a ClusterSecretStore.
                                 type: string
                                 type: string
                               type:
                               type:
                                 description: The type of provider to use such as "Secret",
                                 description: The type of provider to use such as "Secret",
@@ -2590,15 +2607,16 @@ spec:
                           Vault server certificate.
                           Vault server certificate.
                         properties:
                         properties:
                           key:
                           key:
-                            description: The key the value inside of the provider
-                              type to use, only used with "Secret" type
+                            description: The key where the CA certificate can be found
+                              in the Secret or ConfigMap.
                             type: string
                             type: string
                           name:
                           name:
                             description: The name of the object located at the provider
                             description: The name of the object located at the provider
                               type.
                               type.
                             type: string
                             type: string
                           namespace:
                           namespace:
-                            description: The namespace the Provider type is in.
+                            description: The namespace the Provider type is in. Can
+                              only be defined when used in a ClusterSecretStore.
                             type: string
                             type: string
                           type:
                           type:
                             description: The type of provider to use such as "Secret",
                             description: The type of provider to use such as "Secret",

+ 8 - 0
config/crds/bases/kustomization.yaml

@@ -0,0 +1,8 @@
+---
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+  - external-secrets.io_clusterexternalsecrets.yaml
+  - external-secrets.io_clustersecretstores.yaml
+  - external-secrets.io_externalsecrets.yaml
+  - external-secrets.io_secretstores.yaml

+ 2 - 2
deploy/charts/external-secrets/Chart.yaml

@@ -2,8 +2,8 @@ apiVersion: v2
 name: external-secrets
 name: external-secrets
 description: External secret management for Kubernetes
 description: External secret management for Kubernetes
 type: application
 type: application
-version: "0.5.8"
-appVersion: "v0.5.8"
+version: "0.5.9"
+appVersion: "v0.5.9"
 kubeVersion: ">= 1.19.0-0"
 kubeVersion: ">= 1.19.0-0"
 keywords:
 keywords:
   - kubernetes-external-secrets
   - kubernetes-external-secrets

+ 10 - 0
deploy/charts/external-secrets/README.md

@@ -47,6 +47,9 @@ The command removes all the Kubernetes components associated with the chart and
 | certController.image.repository | string | `"ghcr.io/external-secrets/external-secrets"` |  |
 | certController.image.repository | string | `"ghcr.io/external-secrets/external-secrets"` |  |
 | certController.image.tag | string | `""` |  |
 | certController.image.tag | string | `""` |  |
 | certController.imagePullSecrets | list | `[]` |  |
 | certController.imagePullSecrets | list | `[]` |  |
+| certController.metrics.service.annotations | object | `{}` | Additional service annotations |
+| certController.metrics.service.enabled | bool | `false` | Enable if you use another monitoring tool than Prometheus to scrape the metrics |
+| certController.metrics.service.port | int | `8080` | Metrics service port to scrape |
 | certController.nameOverride | string | `""` |  |
 | certController.nameOverride | string | `""` |  |
 | certController.nodeSelector | object | `{}` |  |
 | certController.nodeSelector | object | `{}` |  |
 | certController.podAnnotations | object | `{}` | Annotations to add to Pod |
 | certController.podAnnotations | object | `{}` | Annotations to add to Pod |
@@ -76,6 +79,7 @@ The command removes all the Kubernetes components associated with the chart and
 | crds.createClusterSecretStore | bool | `true` | If true, create CRDs for Cluster Secret Store. |
 | crds.createClusterSecretStore | bool | `true` | If true, create CRDs for Cluster Secret Store. |
 | createOperator | bool | `true` | Specifies whether an external secret operator deployment be created. |
 | createOperator | bool | `true` | Specifies whether an external secret operator deployment be created. |
 | deploymentAnnotations | object | `{}` | Annotations to add to Deployment |
 | deploymentAnnotations | object | `{}` | Annotations to add to Deployment |
+| dnsConfig | object | `{}` | Specifies `dnsOptions` to deployment |
 | extraArgs | object | `{}` |  |
 | extraArgs | object | `{}` |  |
 | extraEnv | list | `[]` |  |
 | extraEnv | list | `[]` |  |
 | extraVolumeMounts | list | `[]` |  |
 | extraVolumeMounts | list | `[]` |  |
@@ -87,6 +91,9 @@ The command removes all the Kubernetes components associated with the chart and
 | imagePullSecrets | list | `[]` |  |
 | imagePullSecrets | list | `[]` |  |
 | installCRDs | bool | `true` | If set, install and upgrade CRDs through helm chart. |
 | installCRDs | bool | `true` | If set, install and upgrade CRDs through helm chart. |
 | leaderElect | bool | `false` | If true, external-secrets will perform leader election between instances to ensure no more than one instance of external-secrets operates at a time. |
 | leaderElect | bool | `false` | If true, external-secrets will perform leader election between instances to ensure no more than one instance of external-secrets operates at a time. |
+| metrics.service.annotations | object | `{}` | Additional service annotations |
+| metrics.service.enabled | bool | `false` | Enable if you use another monitoring tool than Prometheus to scrape the metrics |
+| metrics.service.port | int | `8080` | Metrics service port to scrape |
 | nameOverride | string | `""` |  |
 | nameOverride | string | `""` |  |
 | nodeSelector | object | `{}` |  |
 | nodeSelector | object | `{}` |  |
 | podAnnotations | object | `{}` | Annotations to add to Pod |
 | podAnnotations | object | `{}` | Annotations to add to Pod |
@@ -130,6 +137,9 @@ The command removes all the Kubernetes components associated with the chart and
 | webhook.image.tag | string | `""` | The image tag to use. The default is the chart appVersion. |
 | webhook.image.tag | string | `""` | The image tag to use. The default is the chart appVersion. |
 | webhook.imagePullSecrets | list | `[]` |  |
 | webhook.imagePullSecrets | list | `[]` |  |
 | webhook.lookaheadInterval | string | `""` | Specifices the lookaheadInterval for certificate validity |
 | webhook.lookaheadInterval | string | `""` | Specifices the lookaheadInterval for certificate validity |
+| webhook.metrics.service.annotations | object | `{}` | Additional service annotations |
+| webhook.metrics.service.enabled | bool | `false` | Enable if you use another monitoring tool than Prometheus to scrape the metrics |
+| webhook.metrics.service.port | int | `8080` | Metrics service port to scrape |
 | webhook.nameOverride | string | `""` |  |
 | webhook.nameOverride | string | `""` |  |
 | webhook.nodeSelector | object | `{}` |  |
 | webhook.nodeSelector | object | `{}` |  |
 | webhook.podAnnotations | object | `{}` | Annotations to add to Pod |
 | webhook.podAnnotations | object | `{}` | Annotations to add to Pod |

+ 0 - 1
deploy/charts/external-secrets/README.md.gotmpl

@@ -1,4 +1,3 @@
-{{- $valuesYAML := "https://github.com/external-secrets/external-secrets/blob/master/deploy/charts/external-secrets/values.yaml" -}}
 {{- $chartRepo := "https://charts.external-secrets.io" -}}
 {{- $chartRepo := "https://charts.external-secrets.io" -}}
 {{- $org := "external-secrets" -}}
 {{- $org := "external-secrets" -}}
 # External Secrets
 # External Secrets

+ 13 - 2
deploy/charts/external-secrets/templates/cert-controller-service.yaml

@@ -1,20 +1,31 @@
-{{- if and .Values.certController.create .Values.certController.prometheus.enabled }}
+{{- if or (and .Values.certController.create .Values.certController.prometheus.enabled) (and .Values.certController.create .Values.certController.metrics.service.enabled) }}
 apiVersion: v1
 apiVersion: v1
 kind: Service
 kind: Service
 metadata:
 metadata:
   name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics
   name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics
   labels:
   labels:
     {{- include "external-secrets.labels" . | nindent 4 }}
     {{- include "external-secrets.labels" . | nindent 4 }}
+  {{- if .Values.certController.prometheus.enabled }}
   annotations:
   annotations:
     prometheus.io/path: "/metrics"
     prometheus.io/path: "/metrics"
     prometheus.io/scrape: "true"
     prometheus.io/scrape: "true"
     prometheus.io/port: {{ .Values.certController.prometheus.service.port | quote }}
     prometheus.io/port: {{ .Values.certController.prometheus.service.port | quote }}
+  {{- else }}
+  {{- with .Values.metrics.service.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+  {{- end }}
 spec:
 spec:
   type: ClusterIP
   type: ClusterIP
   ports:
   ports:
+  {{- if .Values.certController.prometheus.enabled }}
   - port: {{ .Values.certController.prometheus.service.port }}
   - port: {{ .Values.certController.prometheus.service.port }}
+  {{- else }}
+  - port: {{ .Values.certController.metrics.service.port }}
+  {{- end }}
     protocol: TCP
     protocol: TCP
     name: metrics
     name: metrics
   selector:
   selector:
     {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 4 }}
     {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 4 }}
-{{- end }}
+{{- end }}

+ 4 - 0
deploy/charts/external-secrets/templates/deployment.yaml

@@ -93,6 +93,10 @@ spec:
           volumeMounts:
           volumeMounts:
           {{- toYaml .Values.extraVolumeMounts | nindent 12 }}
           {{- toYaml .Values.extraVolumeMounts | nindent 12 }}
           {{- end }}
           {{- end }}
+      {{- if .Values.dnsConfig }}
+      dnsConfig:
+          {{- toYaml .Values.dnsConfig | nindent 8 }}
+      {{- end }}
       {{- if .Values.extraVolumes }}
       {{- if .Values.extraVolumes }}
       volumes:
       volumes:
       {{- toYaml .Values.extraVolumes | nindent 8 }}
       {{- toYaml .Values.extraVolumes | nindent 8 }}

+ 13 - 2
deploy/charts/external-secrets/templates/service.yaml

@@ -1,4 +1,4 @@
-{{- if .Values.prometheus.enabled }}
+{{- if or .Values.prometheus.enabled .Values.metrics.service.enabled }}
 apiVersion: v1
 apiVersion: v1
 kind: Service
 kind: Service
 metadata:
 metadata:
@@ -6,16 +6,27 @@ metadata:
   namespace: {{ .Release.Namespace | quote }}
   namespace: {{ .Release.Namespace | quote }}
   labels:
   labels:
     {{- include "external-secrets.labels" . | nindent 4 }}
     {{- include "external-secrets.labels" . | nindent 4 }}
+  {{- if .Values.prometheus.enabled }}
   annotations:
   annotations:
     prometheus.io/path: "/metrics"
     prometheus.io/path: "/metrics"
     prometheus.io/scrape: "true"
     prometheus.io/scrape: "true"
     prometheus.io/port: {{ .Values.prometheus.service.port | quote }}
     prometheus.io/port: {{ .Values.prometheus.service.port | quote }}
+  {{- else }}
+  {{- with .Values.metrics.service.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+  {{- end }}
 spec:
 spec:
   type: ClusterIP
   type: ClusterIP
   ports:
   ports:
+    {{- if .Values.prometheus.enabled }}
     - port: {{ .Values.prometheus.service.port }}
     - port: {{ .Values.prometheus.service.port }}
+    {{- else }}
+    - port: {{ .Values.metrics.service.port }}
+    {{- end }}
       protocol: TCP
       protocol: TCP
       name: metrics
       name: metrics
   selector:
   selector:
     {{- include "external-secrets.selectorLabels" . | nindent 4 }}
     {{- include "external-secrets.selectorLabels" . | nindent 4 }}
-{{- end }}
+{{- end }}

+ 14 - 4
deploy/charts/external-secrets/templates/webhook-service.yaml

@@ -12,6 +12,11 @@ metadata:
     prometheus.io/path: "/metrics"
     prometheus.io/path: "/metrics"
     prometheus.io/scrape: "true"
     prometheus.io/scrape: "true"
     prometheus.io/port: {{ .Values.prometheus.service.port | quote }}
     prometheus.io/port: {{ .Values.prometheus.service.port | quote }}
+  {{- else }}
+  {{- with .Values.metrics.service.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
   {{- end }}
   {{- end }}
 spec:
 spec:
   type: ClusterIP
   type: ClusterIP
@@ -20,12 +25,17 @@ spec:
     targetPort: {{ .Values.webhook.port }}
     targetPort: {{ .Values.webhook.port }}
     protocol: TCP
     protocol: TCP
     name: webhook
     name: webhook
-  {{- if .Values.webhook.prometheus.enabled}}
-  - port: {{ .Values.webhook.prometheus.service.port}}
-    targetPort: {{ .Values.webhook.prometheus.service.port}}
+  {{- if or .Values.webhook.prometheus.enabled .Values.webhook.metrics.service.enabled }}
+  {{- if .Values.webhook.prometheus.enabled }}
+  - port: {{ .Values.webhook.prometheus.service.port }}
+    targetPort: {{ .Values.webhook.prometheus.service.port }}
+  {{- else }}
+  - port: {{ .Values.webhook.metrics.service.port }}
+    targetPort: {{ .Values.webhook.metrics.service.port }}
+  {{- end }}
     protocol: TCP
     protocol: TCP
     name: metrics
     name: metrics
   {{- end }}
   {{- end }}
   selector:
   selector:
     {{- include "external-secrets-webhook.selectorLabels" . | nindent 4 }}
     {{- include "external-secrets-webhook.selectorLabels" . | nindent 4 }}
-{{- end }}
+{{- end }}

+ 37 - 0
deploy/charts/external-secrets/values.yaml

@@ -121,6 +121,17 @@ serviceMonitor:
   # -- Timeout if metrics can't be retrieved in given time interval
   # -- Timeout if metrics can't be retrieved in given time interval
   scrapeTimeout: 25s
   scrapeTimeout: 25s
 
 
+metrics:
+  service:
+    # -- Enable if you use another monitoring tool than Prometheus to scrape the metrics
+    enabled: false
+
+    # -- Metrics service port to scrape
+    port: 8080
+
+    # -- Additional service annotations
+    annotations: {}
+
 nodeSelector: {}
 nodeSelector: {}
 
 
 tolerations: []
 tolerations: []
@@ -206,6 +217,17 @@ webhook:
     # -- Timeout if metrics can't be retrieved in given time interval
     # -- Timeout if metrics can't be retrieved in given time interval
     scrapeTimeout: 25s
     scrapeTimeout: 25s
 
 
+  metrics:
+    service:
+      # -- Enable if you use another monitoring tool than Prometheus to scrape the metrics
+      enabled: false
+
+      # -- Metrics service port to scrape
+      port: 8080
+
+      # -- Additional service annotations
+      annotations: {}
+
     ## -- Extra environment variables to add to container.
     ## -- Extra environment variables to add to container.
   extraEnv: []
   extraEnv: []
 
 
@@ -305,12 +327,24 @@ certController:
     # -- Timeout if metrics can't be retrieved in given time interval
     # -- Timeout if metrics can't be retrieved in given time interval
     scrapeTimeout: 25s
     scrapeTimeout: 25s
 
 
+  metrics:
+    service:
+      # -- Enable if you use another monitoring tool than Prometheus to scrape the metrics
+      enabled: false
+
+      # -- Metrics service port to scrape
+      port: 8080
+
+      # -- Additional service annotations
+      annotations: {}
+
     ## -- Extra environment variables to add to container.
     ## -- Extra environment variables to add to container.
   extraEnv: []
   extraEnv: []
 
 
     ## -- Map of extra arguments to pass to container.
     ## -- Map of extra arguments to pass to container.
   extraArgs: {}
   extraArgs: {}
 
 
+
     ## -- Extra volumes to pass to pod.
     ## -- Extra volumes to pass to pod.
   extraVolumes: []
   extraVolumes: []
 
 
@@ -340,3 +374,6 @@ certController:
       # requests:
       # requests:
       #   cpu: 10m
       #   cpu: 10m
       #   memory: 32Mi
       #   memory: 32Mi
+
+# -- Specifies `dnsOptions` to deployment
+dnsConfig: {}

+ 95 - 26
deploy/crds/bundle.yaml

@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 kind: CustomResourceDefinition
 metadata:
 metadata:
   annotations:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.9.0
+    controller-gen.kubebuilder.io/version: v0.9.2
   creationTimestamp: null
   creationTimestamp: null
   name: clusterexternalsecrets.external-secrets.io
   name: clusterexternalsecrets.external-secrets.io
 spec:
 spec:
@@ -67,7 +67,7 @@ spec:
                                 type: string
                                 type: string
                               decodingStrategy:
                               decodingStrategy:
                                 default: None
                                 default: None
-                                description: Used to define a conversion Strategy
+                                description: Used to define a decoding Strategy
                                 type: string
                                 type: string
                               key:
                               key:
                                 description: Key is the key used in the Provider, mandatory
                                 description: Key is the key used in the Provider, mandatory
@@ -94,8 +94,6 @@ spec:
                     dataFrom:
                     dataFrom:
                       description: DataFrom is used to fetch all properties from a specific Provider data If multiple entries are specified, the Secret keys are merged in the specified order
                       description: DataFrom is used to fetch all properties from a specific Provider data If multiple entries are specified, the Secret keys are merged in the specified order
                       items:
                       items:
-                        maxProperties: 1
-                        minProperties: 1
                         properties:
                         properties:
                           extract:
                           extract:
                             description: Used to extract multiple key/value pairs from one secret
                             description: Used to extract multiple key/value pairs from one secret
@@ -106,7 +104,7 @@ spec:
                                 type: string
                                 type: string
                               decodingStrategy:
                               decodingStrategy:
                                 default: None
                                 default: None
-                                description: Used to define a conversion Strategy
+                                description: Used to define a decoding Strategy
                                 type: string
                                 type: string
                               key:
                               key:
                                 description: Key is the key used in the Provider, mandatory
                                 description: Key is the key used in the Provider, mandatory
@@ -132,7 +130,7 @@ spec:
                                 type: string
                                 type: string
                               decodingStrategy:
                               decodingStrategy:
                                 default: None
                                 default: None
-                                description: Used to define a conversion Strategy
+                                description: Used to define a decoding Strategy
                                 type: string
                                 type: string
                               name:
                               name:
                                 description: Finds secrets based on the name.
                                 description: Finds secrets based on the name.
@@ -150,6 +148,25 @@ spec:
                                 description: Find secrets based on tags.
                                 description: Find secrets based on tags.
                                 type: object
                                 type: object
                             type: object
                             type: object
+                          rewrite:
+                            description: Used to rewrite secret Keys after getting them from the secret Provider Multiple Rewrite operations can be provided. They are applied in a layered order (first to last)
+                            items:
+                              properties:
+                                regexp:
+                                  description: Used to rewrite with regular expressions. The resulting key will be the output of a regexp.ReplaceAll operation.
+                                  properties:
+                                    source:
+                                      description: Used to define the regular expression of a re.Compiler.
+                                      type: string
+                                    target:
+                                      description: Used to define the target pattern of a ReplaceAll operation.
+                                      type: string
+                                  required:
+                                    - source
+                                    - target
+                                  type: object
+                              type: object
+                            type: array
                         type: object
                         type: object
                       type: array
                       type: array
                     refreshInterval:
                     refreshInterval:
@@ -169,6 +186,9 @@ spec:
                         - name
                         - name
                       type: object
                       type: object
                     target:
                     target:
+                      default:
+                        creationPolicy: Owner
+                        deletionPolicy: Retain
                       description: ExternalSecretTarget defines the Kubernetes Secret to be created There can be only one target per ExternalSecret.
                       description: ExternalSecretTarget defines the Kubernetes Secret to be created There can be only one target per ExternalSecret.
                       properties:
                       properties:
                         creationPolicy:
                         creationPolicy:
@@ -294,6 +314,7 @@ spec:
                       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.
                       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
                   type: object
                   type: object
+                  x-kubernetes-map-type: atomic
                 refreshTime:
                 refreshTime:
                   description: The time in which the controller should reconcile it's objects and recheck namespaces for labels.
                   description: The time in which the controller should reconcile it's objects and recheck namespaces for labels.
                   type: string
                   type: string
@@ -359,7 +380,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 kind: CustomResourceDefinition
 metadata:
 metadata:
   annotations:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.9.0
+    controller-gen.kubebuilder.io/version: v0.9.2
   creationTimestamp: null
   creationTimestamp: null
   name: clustersecretstores.external-secrets.io
   name: clustersecretstores.external-secrets.io
 spec:
 spec:
@@ -1771,7 +1792,23 @@ spec:
                       properties:
                       properties:
                         auth:
                         auth:
                           description: Auth configures how secret-manager authenticates with the IBM secrets manager.
                           description: Auth configures how secret-manager authenticates with the IBM secrets manager.
+                          maxProperties: 1
+                          minProperties: 1
                           properties:
                           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:
                             secretRef:
                               properties:
                               properties:
                                 secretApiKeySecretRef:
                                 secretApiKeySecretRef:
@@ -1788,8 +1825,6 @@ spec:
                                       type: string
                                       type: string
                                   type: object
                                   type: object
                               type: object
                               type: object
-                          required:
-                            - secretRef
                           type: object
                           type: object
                         serviceUrl:
                         serviceUrl:
                           description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance
                           description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance
@@ -1880,13 +1915,13 @@ spec:
                               description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider'
                               description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider'
                               properties:
                               properties:
                                 key:
                                 key:
-                                  description: The key the value inside of the provider type to use, only used with "Secret" type
+                                  description: The key where the CA certificate can be found in the Secret or ConfigMap.
                                   type: string
                                   type: string
                                 name:
                                 name:
                                   description: The name of the object located at the provider type.
                                   description: The name of the object located at the provider type.
                                   type: string
                                   type: string
                                 namespace:
                                 namespace:
-                                  description: The namespace the Provider type is in.
+                                  description: The namespace the Provider type is in. Can only be defined when used in a ClusterSecretStore.
                                   type: string
                                   type: string
                                 type:
                                 type:
                                   description: The type of provider to use such as "Secret", or "ConfigMap".
                                   description: The type of provider to use such as "Secret", or "ConfigMap".
@@ -2252,13 +2287,13 @@ spec:
                           description: The provider for the CA bundle to use to validate Vault server certificate.
                           description: The provider for the CA bundle to use to validate Vault server certificate.
                           properties:
                           properties:
                             key:
                             key:
-                              description: The key the value inside of the provider type to use, only used with "Secret" type
+                              description: The key where the CA certificate can be found in the Secret or ConfigMap.
                               type: string
                               type: string
                             name:
                             name:
                               description: The name of the object located at the provider type.
                               description: The name of the object located at the provider type.
                               type: string
                               type: string
                             namespace:
                             namespace:
-                              description: The namespace the Provider type is in.
+                              description: The namespace the Provider type is in. Can only be defined when used in a ClusterSecretStore.
                               type: string
                               type: string
                             type:
                             type:
                               description: The type of provider to use such as "Secret", or "ConfigMap".
                               description: The type of provider to use such as "Secret", or "ConfigMap".
@@ -2526,7 +2561,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 kind: CustomResourceDefinition
 metadata:
 metadata:
   annotations:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.9.0
+    controller-gen.kubebuilder.io/version: v0.9.2
   creationTimestamp: null
   creationTimestamp: null
   name: externalsecrets.external-secrets.io
   name: externalsecrets.external-secrets.io
 spec:
 spec:
@@ -2801,7 +2836,7 @@ spec:
                             type: string
                             type: string
                           decodingStrategy:
                           decodingStrategy:
                             default: None
                             default: None
-                            description: Used to define a conversion Strategy
+                            description: Used to define a decoding Strategy
                             type: string
                             type: string
                           key:
                           key:
                             description: Key is the key used in the Provider, mandatory
                             description: Key is the key used in the Provider, mandatory
@@ -2828,8 +2863,6 @@ spec:
                 dataFrom:
                 dataFrom:
                   description: DataFrom is used to fetch all properties from a specific Provider data If multiple entries are specified, the Secret keys are merged in the specified order
                   description: DataFrom is used to fetch all properties from a specific Provider data If multiple entries are specified, the Secret keys are merged in the specified order
                   items:
                   items:
-                    maxProperties: 1
-                    minProperties: 1
                     properties:
                     properties:
                       extract:
                       extract:
                         description: Used to extract multiple key/value pairs from one secret
                         description: Used to extract multiple key/value pairs from one secret
@@ -2840,7 +2873,7 @@ spec:
                             type: string
                             type: string
                           decodingStrategy:
                           decodingStrategy:
                             default: None
                             default: None
-                            description: Used to define a conversion Strategy
+                            description: Used to define a decoding Strategy
                             type: string
                             type: string
                           key:
                           key:
                             description: Key is the key used in the Provider, mandatory
                             description: Key is the key used in the Provider, mandatory
@@ -2866,7 +2899,7 @@ spec:
                             type: string
                             type: string
                           decodingStrategy:
                           decodingStrategy:
                             default: None
                             default: None
-                            description: Used to define a conversion Strategy
+                            description: Used to define a decoding Strategy
                             type: string
                             type: string
                           name:
                           name:
                             description: Finds secrets based on the name.
                             description: Finds secrets based on the name.
@@ -2884,6 +2917,25 @@ spec:
                             description: Find secrets based on tags.
                             description: Find secrets based on tags.
                             type: object
                             type: object
                         type: object
                         type: object
+                      rewrite:
+                        description: Used to rewrite secret Keys after getting them from the secret Provider Multiple Rewrite operations can be provided. They are applied in a layered order (first to last)
+                        items:
+                          properties:
+                            regexp:
+                              description: Used to rewrite with regular expressions. The resulting key will be the output of a regexp.ReplaceAll operation.
+                              properties:
+                                source:
+                                  description: Used to define the regular expression of a re.Compiler.
+                                  type: string
+                                target:
+                                  description: Used to define the target pattern of a ReplaceAll operation.
+                                  type: string
+                              required:
+                                - source
+                                - target
+                              type: object
+                          type: object
+                        type: array
                     type: object
                     type: object
                   type: array
                   type: array
                 refreshInterval:
                 refreshInterval:
@@ -2903,6 +2955,9 @@ spec:
                     - name
                     - name
                   type: object
                   type: object
                 target:
                 target:
+                  default:
+                    creationPolicy: Owner
+                    deletionPolicy: Retain
                   description: ExternalSecretTarget defines the Kubernetes Secret to be created There can be only one target per ExternalSecret.
                   description: ExternalSecretTarget defines the Kubernetes Secret to be created There can be only one target per ExternalSecret.
                   properties:
                   properties:
                     creationPolicy:
                     creationPolicy:
@@ -3048,7 +3103,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 kind: CustomResourceDefinition
 metadata:
 metadata:
   annotations:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.9.0
+    controller-gen.kubebuilder.io/version: v0.9.2
   creationTimestamp: null
   creationTimestamp: null
   name: pushsecrets.external-secrets.io
   name: pushsecrets.external-secrets.io
 spec:
 spec:
@@ -4608,7 +4663,23 @@ spec:
                       properties:
                       properties:
                         auth:
                         auth:
                           description: Auth configures how secret-manager authenticates with the IBM secrets manager.
                           description: Auth configures how secret-manager authenticates with the IBM secrets manager.
+                          maxProperties: 1
+                          minProperties: 1
                           properties:
                           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:
                             secretRef:
                               properties:
                               properties:
                                 secretApiKeySecretRef:
                                 secretApiKeySecretRef:
@@ -4625,8 +4696,6 @@ spec:
                                       type: string
                                       type: string
                                   type: object
                                   type: object
                               type: object
                               type: object
-                          required:
-                            - secretRef
                           type: object
                           type: object
                         serviceUrl:
                         serviceUrl:
                           description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance
                           description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance
@@ -4717,13 +4786,13 @@ spec:
                               description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider'
                               description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider'
                               properties:
                               properties:
                                 key:
                                 key:
-                                  description: The key the value inside of the provider type to use, only used with "Secret" type
+                                  description: The key where the CA certificate can be found in the Secret or ConfigMap.
                                   type: string
                                   type: string
                                 name:
                                 name:
                                   description: The name of the object located at the provider type.
                                   description: The name of the object located at the provider type.
                                   type: string
                                   type: string
                                 namespace:
                                 namespace:
-                                  description: The namespace the Provider type is in.
+                                  description: The namespace the Provider type is in. Can only be defined when used in a ClusterSecretStore.
                                   type: string
                                   type: string
                                 type:
                                 type:
                                   description: The type of provider to use such as "Secret", or "ConfigMap".
                                   description: The type of provider to use such as "Secret", or "ConfigMap".
@@ -5089,13 +5158,13 @@ spec:
                           description: The provider for the CA bundle to use to validate Vault server certificate.
                           description: The provider for the CA bundle to use to validate Vault server certificate.
                           properties:
                           properties:
                             key:
                             key:
-                              description: The key the value inside of the provider type to use, only used with "Secret" type
+                              description: The key where the CA certificate can be found in the Secret or ConfigMap.
                               type: string
                               type: string
                             name:
                             name:
                               description: The name of the object located at the provider type.
                               description: The name of the object located at the provider type.
                               type: string
                               type: string
                             namespace:
                             namespace:
-                              description: The namespace the Provider type is in.
+                              description: The namespace the Provider type is in. Can only be defined when used in a ClusterSecretStore.
                               type: string
                               type: string
                             type:
                             type:
                               description: The type of provider to use such as "Secret", or "ConfigMap".
                               description: The type of provider to use such as "Secret", or "ConfigMap".

+ 105 - 0
docs/guides-datafrom-rewrite.md

@@ -0,0 +1,105 @@
+# Rewriting Keys in DataFrom
+
+When calling out an ExternalSecret with `dataFrom.extract` or `dataFrom.find`, it is possible that you end up with a kubernetes secret that has conflicts in the key names, or that you simply want to remove a common path from the secret keys.
+
+In order to do so, it is possible to define a set of rewrite operations using `dataFrom.rewrite`. These operations can be stacked, hence allowing complex manipulations of the secret keys.
+
+Rewrite operations are all applied before `ConversionStrategy` is applied.
+
+## Methods
+
+### Regexp
+This method implements rewriting through the use of regular expressions. It needs a `source` and a `target` field. The source field is where the definition of the matching regular expression goes, where the `target` field is where the replacing expression goes.
+
+Some considerations about the impelementation of Regexp Rewrite:
+
+1. The input of a subsequent rewrite operation are the outputs of the previous rewrite.
+2. If a given set of keys do not match any Rewrite operation, there will be no error. Rather, the original keys will be used.
+3. If a `source` is not a compilable `regexp` expression, an error will be produced and the external secret goes into a error state.
+
+## Examples
+### Removing a common path from find operations
+The following ExternalSecret:
+```yaml
+{% include 'datafrom-rewrite-remove-path.yaml' %}
+```
+Will get all the secrets matching `path/to/my/secrets/*` and then rewrite them by removing the common path away.
+
+In this example, if we had the following secrets available in the provider:
+```
+path/to/my/secrets/username
+path/to/my/secrets/password
+```
+the output kubernetes secret would be:
+```yaml
+apiVersion: v1
+kind: Secret
+type: Opaque
+data:
+    username: ...
+    password: ...
+```
+### Avoiding key collisions
+The following ExternalSecret:
+```yaml
+{% include 'datafrom-rewrite-conflict.yaml' %}
+
+```
+Will allow two secrets with the same JSON keys to be imported into a Kubernetes Secret without any conflict.
+In this example, if we had the following secrets available in the provider:
+```json
+{
+    "my-secrets-dev": {
+        "password": "bar",
+     },
+    "my-secrets-prod": {
+        "password": "safebar",
+     }
+}
+```
+the output kubernetes secret would be:
+```yaml
+apiVersion: v1
+kind: Secret
+type: Opaque
+data:
+    dev_password: YmFy #bar
+    prod_password: c2FmZWJhcg== #safebar
+```
+
+### Remove invalid characters
+The following ExternalSecret:
+```yaml
+{% include 'datafrom-rewrite-invalid-characters.yaml' %}
+
+```
+Will remove invalid characters from the secret key.
+In this example, if we had the following secrets available in the provider:
+```json
+{
+    "development": {
+        "foo/bar": "1111",
+        "foo$baz": "2222"
+    }
+}
+```
+the output kubernetes secret would be:
+```yaml
+apiVersion: v1
+kind: Secret
+type: Opaque
+data:
+    foo_bar: MTExMQ== #1111
+    foo_baz: MjIyMg== #2222
+```
+
+## Limitations
+
+Regexp Rewrite is based on golang `regexp`, which in turns implements `RE2` regexp language. There a a series of known limitations to this implementation, such as:
+
+* Lack of ability to do lookaheads or lookbehinds;
+* Lack of negation expressions;
+* Lack of support to conditionl branches;
+* Lack of support to possessive repetitions.
+
+A list of compatibility and known limitations considering other commonly used regexp frameworks (such as PCRE and PERL) are listed [here](https://github.com/google/re2/wiki/Syntax).

+ 7 - 2
docs/guides-getallsecrets.md

@@ -3,7 +3,7 @@
 In some use cases, it might be impractical to bundle all sensitive information into a single secret, or even it is not possible to fully know a given secret name. In such cases, it is possible that an user might need to sync multiple secrets from an external provider into a single Kubernetes Secret. This is possible to be done in external-secrets with the `dataFrom.find` option.
 In some use cases, it might be impractical to bundle all sensitive information into a single secret, or even it is not possible to fully know a given secret name. In such cases, it is possible that an user might need to sync multiple secrets from an external provider into a single Kubernetes Secret. This is possible to be done in external-secrets with the `dataFrom.find` option.
 
 
 !!! note
 !!! note
-    The secret's contents as defined in the provider are going to be stored in the kubernetes secret as a single key. Currently, it is not possible to apply any decoding Strategy during a find operation.
+    The secret's contents as defined in the provider are going to be stored in the kubernetes secret as a single key. Currently, it possible to apply a decoding Strategy during a find operation, but only at the secret level (e.g. if a secret is a JSON with some B64 encoded data within, `decodingStrategy: Auto` would not decode it)
 
 
 
 
 ### Fetching secrets matching a given name pattern
 ### Fetching secrets matching a given name pattern
@@ -33,7 +33,12 @@ Some providers support filtering out a find operation only to a given path, inst
 ### Avoiding name conflicts
 ### Avoiding name conflicts
 By default, kubernetes Secrets accepts only a given range of characters. `Find` operations will automatically replace any not allowed character with a `_`. So if we have a given secret `a_c` and `a/c` would lead to a naming conflict. 
 By default, kubernetes Secrets accepts only a given range of characters. `Find` operations will automatically replace any not allowed character with a `_`. So if we have a given secret `a_c` and `a/c` would lead to a naming conflict. 
 
 
-It is not entirely possible to avoid this behavior, but setting `dataFrom.find.conversionStrategy: Unicode` reduces the collision probability. When using `Unicode`, any invalid character will be replaced by its unicode, in the form of `_UXXXX_`. In this case, the available kubernetes keys would be `a_c` and `a_U2215_c`, hence avoiding most of possible conflicts.
+
+If you happen to have a case where a conflict is happening, you can use the `rewrite` block to apply a regexp on one of the find operations (for more information please refer to [Rewriting Keys from DataFrom](guides-datafrom-rewrite.md)).
+
+You can also set  `dataFrom.find.conversionStrategy: Unicode` to reduce the collistion probability. When using `Unicode`, any invalid character will be replaced by its unicode, in the form of `_UXXXX_`. In this case, the available kubernetes keys would be `a_c` and `a_U2215_c`, hence avoiding most of possible conflicts.
+
+
 
 
 !!! note "PRs welcome"
 !!! note "PRs welcome"
     Some providers might not have the implementation needed for fetching multiple secrets. If that's your case, please feel free to contribute!
     Some providers might not have the implementation needed for fetching multiple secrets. If that's your case, please feel free to contribute!

+ 2 - 0
docs/guides-metrics.md

@@ -2,6 +2,8 @@
 
 
 The External Secrets Operator exposes its Prometheus metrics in the `/metrics` path. To enable it, set the `serviceMonitor.enabled` Helm flag to `true`. In addition you can also set `webhook.serviceMonitor.enabled=true` and `certController.serviceMonitor.enabled=true` to create `ServiceMonitor` resources for the other components.
 The External Secrets Operator exposes its Prometheus metrics in the `/metrics` path. To enable it, set the `serviceMonitor.enabled` Helm flag to `true`. In addition you can also set `webhook.serviceMonitor.enabled=true` and `certController.serviceMonitor.enabled=true` to create `ServiceMonitor` resources for the other components.
 
 
+If you are using a different monitoring tool that also needs a `/metrics` endpoint, you can set the `metrics.service.enabled` Helm flag to `true`. In addition you can also set `webhook.metrics.service.enabled` and `certController.metrics.service.enabled` to scrape the other components.
+
 The Operator has the metrics inherited from Kubebuilder plus some custom metrics with the `externalsecret` prefix.
 The Operator has the metrics inherited from Kubebuilder plus some custom metrics with the `externalsecret` prefix.
 
 
 ## External Secret Metrics
 ## External Secret Metrics

BIN
docs/pictures/screenshot_container_auth_create_1.png


BIN
docs/pictures/screenshot_container_auth_create_2.png


BIN
docs/pictures/screenshot_container_auth_create_3.png


BIN
docs/pictures/screenshot_container_auth_create_button.png


BIN
docs/pictures/screenshot_container_auth_create_group.png


BIN
docs/pictures/screenshot_container_auth_create_group_1.png


BIN
docs/pictures/screenshot_container_auth_create_group_2.png


BIN
docs/pictures/screenshot_container_auth_create_group_3.png


BIN
docs/pictures/screenshot_container_auth_create_group_4.png


BIN
docs/pictures/screenshot_container_auth_iam_left.png


+ 1 - 1
docs/provider-1password-automation.md

@@ -32,7 +32,7 @@ _**The 1Password API calls the entries in vaults 'Items'. These docs use the sam
     * External Secrets does not run this server. See [Deploy a Connect Server](#deploy-a-connect-server).
     * External Secrets does not run this server. See [Deploy a Connect Server](#deploy-a-connect-server).
     * One Connect Server is needed per 1Password Automation Environment.
     * One Connect Server is needed per 1Password Automation Environment.
     * Many Vaults can be added to an Automation Environment, and Tokens can be generated in that Environment with access to any set or subset of those Vaults.
     * Many Vaults can be added to an Automation Environment, and Tokens can be generated in that Environment with access to any set or subset of those Vaults.
-* 1Password Connect Server version 1.3.0 or higher. 1.3.0 and 1.5.0 have been tested.
+* 1Password Connect Server version 1.5.6 or higher.
 
 
 ### Setup Authentication
 ### Setup Authentication
 _Authentication requires a `1password-credentials.json` file provided to the Connect Server, and a related 'Access Token' for the client in this provider to authenticate to that Connect Server. Both of these are generated by 1Password._
 _Authentication requires a `1password-credentials.json` file provided to the Connect Server, and a related 'Access Token' for the client in this provider to authenticate to that Connect Server. Both of these are generated by 1Password._

+ 21 - 7
docs/provider-azure-key-vault.md

@@ -11,6 +11,13 @@ We support Service Principals, Managed Identity and Workload Identity authentica
 
 
 To use Managed Identity authentication, you should use [aad-pod-identity](https://azure.github.io/aad-pod-identity/docs/) to assign the identity to external-secrets operator. To add the selector to external-secrets operator, use `podLabels` in your values.yaml in case of Helm installation of external-secrets.
 To use Managed Identity authentication, you should use [aad-pod-identity](https://azure.github.io/aad-pod-identity/docs/) to assign the identity to external-secrets operator. To add the selector to external-secrets operator, use `podLabels` in your values.yaml in case of Helm installation of external-secrets.
 
 
+Minimum required permissions are `Get` over secret and certificate permissions. This can be done by adding a Key Vault access policy:
+
+```sh
+KUBELET_IDENTITY_OBJECT_ID=$(az aks show --resource-group <AKS_CLUSTER_RG_NAME> --name <AKS_CLUSTER_NAME> --query 'identityProfile.kubeletidentity.objectId' -o tsv)
+az keyvault set-policy --name kv-name-with-certs --object-id "$KUBELET_IDENTITY_OBJECT_ID" --certificate-permissions get --secret-permissions get
+```
+
 #### Service Principal key authentication
 #### Service Principal key authentication
 
 
 A service Principal client and Secret is created and the JSON keyfile is stored in a `Kind=Secret`. The `ClientID` and `ClientSecret` should be configured for the secret. This service principal should have proper access rights to the keyvault to be managed by the operator
 A service Principal client and Secret is created and the JSON keyfile is stored in a `Kind=Secret`. The `ClientID` and `ClientSecret` should be configured for the secret. This service principal should have proper access rights to the keyvault to be managed by the operator
@@ -89,23 +96,30 @@ Azure KeyVault manages different [object types](https://docs.microsoft.com/en-us
 | `key`         | A JWK which contains the public key. Azure KeyVault does **not** export the private key. You may want to use [template functions](guides-templating.md) to transform this JWK into PEM encoded PKIX ASN.1 DER format. |
 | `key`         | A JWK which contains the public key. Azure KeyVault does **not** export the private key. You may want to use [template functions](guides-templating.md) to transform this JWK into PEM encoded PKIX ASN.1 DER format. |
 | `certificate` | The raw CER contents of the x509 certificate. You may want to use [template functions](guides-templating.md) to transform this into your desired encoding                                                             |
 | `certificate` | The raw CER contents of the x509 certificate. You may want to use [template functions](guides-templating.md) to transform this into your desired encoding                                                             |
 
 
-
 ### Creating external secret
 ### Creating external secret
 
 
 To create a kubernetes secret from the Azure Key vault secret a `Kind=ExternalSecret` is needed.
 To create a kubernetes secret from the Azure Key vault secret a `Kind=ExternalSecret` is needed.
 
 
-You can manage keys/secrets/certificates saved inside the keyvault , by setting a "/" prefixed type in the secret name , the default type is a `secret`. other supported values are `cert` and `key`
-
-to select all secrets inside the key vault or all tags inside a secret, you can use the `dataFrom` directive
+You can manage keys/secrets/certificates saved inside the keyvault , by setting a "/" prefixed type in the secret name, the default type is a `secret`. Other supported values are `cert` and `key`.
 
 
 ```yaml
 ```yaml
 {% include 'azkv-external-secret.yaml' %}
 {% include 'azkv-external-secret.yaml' %}
 ```
 ```
+
+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 <namespace> | -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:
+
 ```yaml
 ```yaml
 {% include 'azkv-datafrom-external-secret.yaml' %}
 {% include 'azkv-datafrom-external-secret.yaml' %}
 ```
 ```
 
 
-The operator will fetch the Azure Key vault secret and inject it as a `Kind=Secret`
+To get a PKCS#12 certificate from Azure Key Vault and inject it as a `Kind=Secret` of type `kubernetes.io/tls`:
+
+```yaml
+{% include 'azkv-pkcs12-cert-external-secret.yaml' %}
 ```
 ```
-kubectl get secret secret-to-be-created -n <namespace> | -o jsonpath='{.data.dev-secret-test}' | base64 -d
-```

+ 66 - 7
docs/provider-ibm-secrets-manager.md

@@ -4,7 +4,11 @@ External Secrets Operator integrates with [IBM Secret Manager](https://www.ibm.c
 
 
 ### Authentication
 ### Authentication
 
 
-At the moment, we only support API key authentication for this provider. To generate your key (for test purposes we are going to generate from your user), first got to your (Access IAM) page:
+We support API key and trusted profile container authentication for this provider.
+
+#### API key secret
+
+To generate your key (for test purposes we are going to generate from your user), first got to your (Access IAM) page:
 
 
 ![iam](./pictures/screenshot_api_keys_iam.png)
 ![iam](./pictures/screenshot_api_keys_iam.png)
 
 
@@ -24,16 +28,68 @@ You have created a key. Press the eyeball to show the key. Copy or save it becau
 
 
 ![iam-create-success](./pictures/screenshot_api_keys_create_successful.png)
 ![iam-create-success](./pictures/screenshot_api_keys_create_successful.png)
 
 
-
-
-#### API key secret
-
 Create a secret containing your apiKey:
 Create a secret containing your apiKey:
 
 
 ```shell
 ```shell
 kubectl create secret generic ibm-secret --from-literal=apiKey='API_KEY_VALUE'
 kubectl create secret generic ibm-secret --from-literal=apiKey='API_KEY_VALUE'
 ```
 ```
 
 
+#### Trusted Profile Container Auth
+
+To create the trusted profile, first got to your (Access IAM) page:
+
+![iam](./pictures/screenshot_api_keys_iam.png)
+
+On the left, click "Access groups":
+
+![iam-left](./pictures/screenshot_container_auth_create_group.png)
+
+Pick a name and description for your group:
+
+![iam-left](./pictures/screenshot_container_auth_create_group_1.png)
+
+Click on "Access Policies":
+
+![iam-left](./pictures/screenshot_container_auth_create_group_2.png)
+
+Click on "Assign Access", select "IAM services", and pick "Secrets Manager" from the pick-list:
+
+![iam-left](./pictures/screenshot_container_auth_create_group_3.png)
+
+Scope to "All resources" or "Resources based on selected attributes", select "SecretsReader":
+
+![iam-left](./pictures/screenshot_container_auth_create_group_4.png)
+
+Click "Add" and "Assign" to save the access group.
+
+Next, on the left, click "Trusted profiles":
+
+![iam-left](./pictures/screenshot_container_auth_iam_left.png)
+
+Press "Create":
+
+![iam-create-button](./pictures/screenshot_container_auth_create_button.png)
+
+Pick a name and description for your profile:
+
+![iam-create-key](./pictures/screenshot_container_auth_create_1.png)
+
+Scope the profile's access.
+
+The compute service type will be "Red Hat OpenShift on IBM Cloud".  Additional restriction can be configured based on cloud or cluster metadata, or if "Specific resources" is selected, restriction to a specific cluster.
+
+![iam-create-key](./pictures/screenshot_container_auth_create_2.png)
+
+Click "Add" next to the previously created access group and then "Create", to associate the necessary service permissions.
+
+![iam-create-key](./pictures/screenshot_container_auth_create_3.png)
+
+To use the container-based authentication, it is necessary to map the API server `serviceAccountToken` auth token to the "external-secrets" and "external-secrets-webhook" deployment descriptors. Example below:
+
+```yaml
+{% include 'ibm-container-auth-volume.yaml' %}
+```
+
 ### Update secret store
 ### Update secret store
 Be sure the `ibm` provider is listed in the `Kind=SecretStore`
 Be sure the `ibm` provider is listed in the `Kind=SecretStore`
 
 
@@ -42,6 +98,9 @@ Be sure the `ibm` provider is listed in the `Kind=SecretStore`
 ```
 ```
 **NOTE:** In case of a `ClusterSecretStore`, Be sure to provide `namespace` in `secretApiKeySecretRef` with the namespace where the secret resides.
 **NOTE:** In case of a `ClusterSecretStore`, Be sure to provide `namespace` in `secretApiKeySecretRef` with the namespace where the secret resides.
 
 
+**NOTE:** Only `secretApiKeySecretRef` or `containerAuth` should be specified, depending on authentication me
+thod being used.
+
 To find your serviceURL, under your Secrets Manager resource, go to "Endpoints" on the left.
 To find your serviceURL, under your Secrets Manager resource, go to "Endpoints" on the left.
 Note: Use the url without the `/api` suffix that is presented in the UI.
 Note: Use the url without the `/api` suffix that is presented in the UI.
 See here for a list of [publicly available endpoints](https://cloud.ibm.com/apidocs/secrets-manager#getting-started-endpoints).
 See here for a list of [publicly available endpoints](https://cloud.ibm.com/apidocs/secrets-manager#getting-started-endpoints).
@@ -51,13 +110,13 @@ See here for a list of [publicly available endpoints](https://cloud.ibm.com/apid
 ### Secret Types
 ### Secret Types
 We support the following secret types of [IBM Secrets Manager](https://cloud.ibm.com/apidocs/secrets-manager):
 We support the following secret types of [IBM Secrets Manager](https://cloud.ibm.com/apidocs/secrets-manager):
 
 
-* `arbitrary`
+* `arbitrary` 
 * `username_password`
 * `username_password`
 * `iam_credentials`
 * `iam_credentials`
 * `imported_cert`
 * `imported_cert`
 * `public_cert`
 * `public_cert`
 * `private_cert`
 * `private_cert`
-* `kv`
+* `kv` 
 
 
 To define the type of secret you would like to sync you need to prefix the secret id with the desired type. If the secret type is not specified it is defaulted to `arbitrary`:
 To define the type of secret you would like to sync you need to prefix the secret id with the desired type. If the secret type is not specified it is defaulted to `arbitrary`:
 
 

+ 24 - 0
docs/snippets/azkv-pkcs12-cert-external-secret.yaml

@@ -0,0 +1,24 @@
+{% raw %}
+apiVersion: external-secrets.io/v1beta1
+kind: ExternalSecret
+metadata:
+  name: mycert
+spec:
+  refreshInterval: 24h
+  secretStoreRef:
+    kind: ClusterSecretStore
+    name: kv-mycert
+  target:
+    template:
+      type: kubernetes.io/tls
+      engineVersion: v2
+      data:
+        tls.crt: "{{ .mycert | b64dec | pkcs12cert }}"
+        tls.key: "{{ .mycert | b64dec | pkcs12key }}"
+  data:
+  - secretKey: mycert
+    remoteRef:
+      # Azure Key Vault certificates must be fetched as secret/cert-name
+      key: secret/mycert
+
+{% endraw %}

+ 24 - 0
docs/snippets/datafrom-rewrite-conflict.yaml

@@ -0,0 +1,24 @@
+apiVersion: external-secrets.io/v1beta1
+kind: ExternalSecret
+metadata:
+  name: example
+spec:
+  refreshInterval: 1h
+  secretStoreRef:
+    kind: SecretStore
+    name: backend
+  target:
+    name: secret-to-be-created
+  dataFrom:
+  - extract:
+      key: my-secrets-dev
+    rewrite:
+    - regexp:
+        source: "(.*)"
+        target: "dev-$1"      
+  - extract:
+      key: my-secrets-prod
+    rewrite:
+    - regexp:
+        source: "(.*)"
+        target: "prod-$1"

+ 18 - 0
docs/snippets/datafrom-rewrite-invalid-characters.yaml

@@ -0,0 +1,18 @@
+apiVersion: external-secrets.io/v1beta1
+kind: ExternalSecret
+metadata:
+  name: example
+spec:
+  refreshInterval: 1h
+  secretStoreRef:
+    kind: SecretStore
+    name: backend
+  target:
+    name: secret-to-be-created
+  dataFrom:
+  - extract:
+      key: development
+    rewrite:
+    - regexp:
+        source: "[^a-zA-Z0-9 -]"
+        target: "_"

+ 20 - 0
docs/snippets/datafrom-rewrite-remove-path.yaml

@@ -0,0 +1,20 @@
+apiVersion: external-secrets.io/v1beta1
+kind: ExternalSecret
+metadata:
+  name: example
+spec:
+  refreshInterval: 1h
+  secretStoreRef:
+    kind: SecretStore
+    name: backend
+  target:
+    name: secret-to-be-created
+  dataFrom:
+  - find:
+      path: path/to/my
+      name: 
+        regexp: secrets
+    rewrite:
+    - regexp:
+        source: "path/to/my/secrets/(.*)"
+        target: "$1"

+ 14 - 0
docs/snippets/full-external-secret.yaml

@@ -85,14 +85,28 @@ spec:
       property: provider-key-property
       property: provider-key-property
       conversionStrategy: Default
       conversionStrategy: Default
       decodingStrategy: Auto
       decodingStrategy: Auto
+    rewrite:
+    - regexp:
+        source: "foo"
+        target: "bar"
+    - regexp:
+        source: "exp-(.*?)-ression"
+        target: "rewriting-$1-with-groups"
   - find:
   - find:
       path: path-to-filter
       path: path-to-filter
+          source: "exp-(.*?)-ression"
+          target: "rewriting-$1-with-groups"
       name:
       name:
         regexp: ".*foobar.*"
         regexp: ".*foobar.*"
       tags:
       tags:
         foo: bar
         foo: bar
       conversionStrategy: Unicode
       conversionStrategy: Unicode
       decodingStrategy: Base64
       decodingStrategy: Base64
+    rewrite:
+    - regexp:
+        source: "foo"
+        target: "bar"
+    - regexp:
 
 
 status:
 status:
   # refreshTime is the time and date the external secret was fetched and
   # refreshTime is the time and date the external secret was fetched and

+ 22 - 0
docs/snippets/ibm-container-auth-volume.yaml

@@ -0,0 +1,22 @@
+...
+spec:
+  ...
+  template:
+    ...
+    spec:
+      containers:
+        ...
+        volumeMounts:
+        - mountPath: /var/run/secrets/tokens
+           name: sa-token
+      ...
+      volumes:
+      - name: sa-token
+        projected:
+          defaultMode: 420
+          sources:
+          - serviceAccountToken:
+              audience: iam
+              expirationSeconds: 3600
+              path: sa-token
+...

+ 4 - 0
docs/snippets/ibm-secret-store.yaml

@@ -7,6 +7,10 @@ spec:
     ibm:
     ibm:
       serviceUrl: "https://SECRETS_MANAGER_ID.REGION.secrets-manager.appdomain.cloud"
       serviceUrl: "https://SECRETS_MANAGER_ID.REGION.secrets-manager.appdomain.cloud"
       auth:
       auth:
+        containerAuth:
+          profile: "test container auth profile"
+          tokenLocation: "/var/run/secrets/tokens/sa-token"
+          iamEndpoint: "https://iam.cloud.ibm.com"
         secretRef:
         secretRef:
           secretApiKeySecretRef:
           secretApiKeySecretRef:
             name: ibm-secret
             name: ibm-secret

+ 216 - 11
docs/spec.md

@@ -494,7 +494,7 @@ is ServicePrincipal.</p>
 </tr>
 </tr>
 </thead>
 </thead>
 <tbody><tr><td><p>&#34;ManagedIdentity&#34;</p></td>
 <tbody><tr><td><p>&#34;ManagedIdentity&#34;</p></td>
-<td><p>Using Managed Identity to authenticate. Used with aad-pod-identity installed in the clister.</p>
+<td><p>Using Managed Identity to authenticate. Used with aad-pod-identity installed in the cluster.</p>
 </td>
 </td>
 </tr><tr><td><p>&#34;ServicePrincipal&#34;</p></td>
 </tr><tr><td><p>&#34;ServicePrincipal&#34;</p></td>
 <td><p>Using service principal to authenticate, which needs a tenantId, a clientId and a clientSecret.</p>
 <td><p>Using service principal to authenticate, which needs a tenantId, a clientId and a clientSecret.</p>
@@ -649,11 +649,13 @@ string
 </h3>
 </h3>
 <p>
 <p>
 (<em>Appears on:</em>
 (<em>Appears on:</em>
-<a href="#external-secrets.io/v1beta1.KubernetesServer">KubernetesServer</a>, 
+<a href="#external-secrets.io/v1beta1.KubernetesServer">KubernetesServer</a>,
 <a href="#external-secrets.io/v1beta1.VaultProvider">VaultProvider</a>)
 <a href="#external-secrets.io/v1beta1.VaultProvider">VaultProvider</a>)
 </p>
 </p>
 <p>
 <p>
-<p>Defines a location to fetch the cert for the vault provider from.</p>
+<p>Used to provide custom certificate authority (CA) certificates
+for a secret store. The CAProvider points to a Secret or ConfigMap resource
+that contains a PEM-encoded certificate.</p>
 </p>
 </p>
 <table>
 <table>
 <thead>
 <thead>
@@ -695,7 +697,7 @@ string
 </em>
 </em>
 </td>
 </td>
 <td>
 <td>
-<p>The key the value inside of the provider type to use, only used with &ldquo;Secret&rdquo; type</p>
+<p>The key where the CA certificate can be found in the Secret or ConfigMap.</p>
 </td>
 </td>
 </tr>
 </tr>
 <tr>
 <tr>
@@ -707,7 +709,8 @@ string
 </td>
 </td>
 <td>
 <td>
 <em>(Optional)</em>
 <em>(Optional)</em>
-<p>The namespace the Provider type is in.</p>
+<p>The namespace the Provider type is in.
+Can only be defined when used in a ClusterSecretStore.</p>
 </td>
 </td>
 </tr>
 </tr>
 </tbody>
 </tbody>
@@ -1385,7 +1388,7 @@ ExternalSecretStatus
 (<code>string</code> alias)</p></h3>
 (<code>string</code> alias)</p></h3>
 <p>
 <p>
 (<em>Appears on:</em>
 (<em>Appears on:</em>
-<a href="#external-secrets.io/v1beta1.ExternalSecretDataRemoteRef">ExternalSecretDataRemoteRef</a>, 
+<a href="#external-secrets.io/v1beta1.ExternalSecretDataRemoteRef">ExternalSecretDataRemoteRef</a>,
 <a href="#external-secrets.io/v1beta1.ExternalSecretFind">ExternalSecretFind</a>)
 <a href="#external-secrets.io/v1beta1.ExternalSecretFind">ExternalSecretFind</a>)
 </p>
 </p>
 <p>
 <p>
@@ -1519,13 +1522,27 @@ ExternalSecretFind
 <p>Used to find secrets based on tags or regular expressions</p>
 <p>Used to find secrets based on tags or regular expressions</p>
 </td>
 </td>
 </tr>
 </tr>
+<tr>
+<td>
+<code>rewrite</code></br>
+<em>
+<a href="#external-secrets.io/v1beta1.ExternalSecretRewrite">
+[]ExternalSecretRewrite
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>Used to rewrite secret Keys after getting them from the secret Provider</p>
+</td>
+</tr>
 </tbody>
 </tbody>
 </table>
 </table>
 <h3 id="external-secrets.io/v1beta1.ExternalSecretDataRemoteRef">ExternalSecretDataRemoteRef
 <h3 id="external-secrets.io/v1beta1.ExternalSecretDataRemoteRef">ExternalSecretDataRemoteRef
 </h3>
 </h3>
 <p>
 <p>
 (<em>Appears on:</em>
 (<em>Appears on:</em>
-<a href="#external-secrets.io/v1beta1.ExternalSecretData">ExternalSecretData</a>, 
+<a href="#external-secrets.io/v1beta1.ExternalSecretData">ExternalSecretData</a>,
 <a href="#external-secrets.io/v1beta1.ExternalSecretDataFromRemoteRef">ExternalSecretDataFromRemoteRef</a>)
 <a href="#external-secrets.io/v1beta1.ExternalSecretDataFromRemoteRef">ExternalSecretDataFromRemoteRef</a>)
 </p>
 </p>
 <p>
 <p>
@@ -1602,8 +1619,48 @@ ExternalSecretConversionStrategy
 <p>Used to define a conversion Strategy</p>
 <p>Used to define a conversion Strategy</p>
 </td>
 </td>
 </tr>
 </tr>
+<tr>
+<td>
+<code>decodingStrategy</code></br>
+<em>
+<a href="#external-secrets.io/v1beta1.ExternalSecretDecodingStrategy">
+ExternalSecretDecodingStrategy
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>Used to define a conversion Strategy</p>
+</td>
+</tr>
 </tbody>
 </tbody>
 </table>
 </table>
+<h3 id="external-secrets.io/v1beta1.ExternalSecretDecodingStrategy">ExternalSecretDecodingStrategy
+(<code>string</code> alias)</p></h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1beta1.ExternalSecretDataRemoteRef">ExternalSecretDataRemoteRef</a>,
+<a href="#external-secrets.io/v1beta1.ExternalSecretFind">ExternalSecretFind</a>)
+</p>
+<p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Value</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody><tr><td><p>&#34;Auto&#34;</p></td>
+<td></td>
+</tr><tr><td><p>&#34;Base64&#34;</p></td>
+<td></td>
+</tr><tr><td><p>&#34;Base64URL&#34;</p></td>
+<td></td>
+</tr><tr><td><p>&#34;None&#34;</p></td>
+<td></td>
+</tr></tbody>
+</table>
 <h3 id="external-secrets.io/v1beta1.ExternalSecretDeletionPolicy">ExternalSecretDeletionPolicy
 <h3 id="external-secrets.io/v1beta1.ExternalSecretDeletionPolicy">ExternalSecretDeletionPolicy
 (<code>string</code> alias)</p></h3>
 (<code>string</code> alias)</p></h3>
 <p>
 <p>
@@ -1707,6 +1764,20 @@ ExternalSecretConversionStrategy
 <p>Used to define a conversion Strategy</p>
 <p>Used to define a conversion Strategy</p>
 </td>
 </td>
 </tr>
 </tr>
+<tr>
+<td>
+<code>decodingStrategy</code></br>
+<em>
+<a href="#external-secrets.io/v1beta1.ExternalSecretDecodingStrategy">
+ExternalSecretDecodingStrategy
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>Used to define a conversion Strategy</p>
+</td>
+</tr>
 </tbody>
 </tbody>
 </table>
 </table>
 <h3 id="external-secrets.io/v1beta1.ExternalSecretMetadataPolicy">ExternalSecretMetadataPolicy
 <h3 id="external-secrets.io/v1beta1.ExternalSecretMetadataPolicy">ExternalSecretMetadataPolicy
@@ -1730,11 +1801,83 @@ ExternalSecretConversionStrategy
 <td></td>
 <td></td>
 </tr></tbody>
 </tr></tbody>
 </table>
 </table>
+<h3 id="external-secrets.io/v1beta1.ExternalSecretRewrite">ExternalSecretRewrite
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1beta1.ExternalSecretDataFromRemoteRef">ExternalSecretDataFromRemoteRef</a>)
+</p>
+<p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>regexp</code></br>
+<em>
+<a href="#external-secrets.io/v1beta1.ExternalSecretRewriteRegexp">
+ExternalSecretRewriteRegexp
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>Rewrite using regular expressions</p>
+</td>
+</tr>
+</tbody>
+</table>
+<h3 id="external-secrets.io/v1beta1.ExternalSecretRewriteRegexp">ExternalSecretRewriteRegexp
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1beta1.ExternalSecretRewrite">ExternalSecretRewrite</a>)
+</p>
+<p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>source</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>Regular expression to use as a re.Compiler.</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>target</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>Target output for a replace operation.</p>
+</td>
+</tr>
+</tbody>
+</table>
 <h3 id="external-secrets.io/v1beta1.ExternalSecretSpec">ExternalSecretSpec
 <h3 id="external-secrets.io/v1beta1.ExternalSecretSpec">ExternalSecretSpec
 </h3>
 </h3>
 <p>
 <p>
 (<em>Appears on:</em>
 (<em>Appears on:</em>
-<a href="#external-secrets.io/v1beta1.ClusterExternalSecretSpec">ClusterExternalSecretSpec</a>, 
+<a href="#external-secrets.io/v1beta1.ClusterExternalSecretSpec">ClusterExternalSecretSpec</a>,
 <a href="#external-secrets.io/v1beta1.ExternalSecret">ExternalSecret</a>)
 <a href="#external-secrets.io/v1beta1.ExternalSecret">ExternalSecret</a>)
 </p>
 </p>
 <p>
 <p>
@@ -2615,6 +2758,69 @@ IBMAuthSecretRef
 <td>
 <td>
 </td>
 </td>
 </tr>
 </tr>
+<tr>
+<td>
+<code>containerAuth</code></br>
+<em>
+<a href="#external-secrets.io/v1beta1.IBMAuthContainerAuth">
+IBMAuthContainerAuth
+</a>
+</em>
+</td>
+<td>
+</td>
+</tr>
+</tbody>
+</table>
+<h3 id="external-secrets.io/v1beta1.IBMAuthContainerAuth">IBMAuthContainerAuth
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1beta1.IBMAuth">IBMAuth</a>)
+</p>
+<p>
+<p>IBM Container-based auth with IAM Trusted Profile.</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>profile</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>the IBM Trusted Profile</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>tokenLocation</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>Location the token is mounted on the pod</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>iamEndpoint</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+</td>
+</tr>
 </tbody>
 </tbody>
 </table>
 </table>
 <h3 id="external-secrets.io/v1beta1.IBMAuthSecretRef">IBMAuthSecretRef
 <h3 id="external-secrets.io/v1beta1.IBMAuthSecretRef">IBMAuthSecretRef
@@ -2641,7 +2847,6 @@ github.com/external-secrets/external-secrets/apis/meta/v1.SecretKeySelector
 </em>
 </em>
 </td>
 </td>
 <td>
 <td>
-<em>(Optional)</em>
 <p>The SecretAccessKey is used for authentication</p>
 <p>The SecretAccessKey is used for authentication</p>
 </td>
 </td>
 </tr>
 </tr>
@@ -3594,7 +3799,7 @@ string
 </h3>
 </h3>
 <p>
 <p>
 (<em>Appears on:</em>
 (<em>Appears on:</em>
-<a href="#external-secrets.io/v1beta1.ClusterSecretStore">ClusterSecretStore</a>, 
+<a href="#external-secrets.io/v1beta1.ClusterSecretStore">ClusterSecretStore</a>,
 <a href="#external-secrets.io/v1beta1.SecretStore">SecretStore</a>)
 <a href="#external-secrets.io/v1beta1.SecretStore">SecretStore</a>)
 </p>
 </p>
 <p>
 <p>
@@ -3666,7 +3871,7 @@ int
 </h3>
 </h3>
 <p>
 <p>
 (<em>Appears on:</em>
 (<em>Appears on:</em>
-<a href="#external-secrets.io/v1beta1.ClusterSecretStore">ClusterSecretStore</a>, 
+<a href="#external-secrets.io/v1beta1.ClusterSecretStore">ClusterSecretStore</a>,
 <a href="#external-secrets.io/v1beta1.SecretStore">SecretStore</a>)
 <a href="#external-secrets.io/v1beta1.SecretStore">SecretStore</a>)
 </p>
 </p>
 <p>
 <p>

+ 0 - 1
e2e/run.sh

@@ -46,7 +46,6 @@ until kubectl get secret | grep -q -e ^external-secrets-e2e-token; do \
 done
 done
 
 
 echo -e "Starting the e2e test pod ${E2E_IMAGE_REGISTRY}:${VERSION}"
 echo -e "Starting the e2e test pod ${E2E_IMAGE_REGISTRY}:${VERSION}"
-
 kubectl run --rm \
 kubectl run --rm \
   --attach \
   --attach \
   --restart=Never \
   --restart=Never \

+ 1 - 0
e2e/suites/provider/cases/akeyless/akeyless.go

@@ -31,6 +31,7 @@ var _ = Describe("[akeyless]", Label("akeyless"), func() {
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.JSONDataFromSync(f)),
 		Entry(common.JSONDataFromSync(f)),
+		Entry(common.JSONDataFromRewrite(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.DockerJSONConfig(f)),
 		Entry(common.DockerJSONConfig(f)),

+ 1 - 0
e2e/suites/provider/cases/alibaba/alibaba.go

@@ -31,6 +31,7 @@ var _ = Describe("[alibaba]", Label("alibaba"), func() {
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.JSONDataFromSync(f)),
 		Entry(common.JSONDataFromSync(f)),
+		Entry(common.JSONDataFromRewrite(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.DockerJSONConfig(f)),
 		Entry(common.DockerJSONConfig(f)),

+ 1 - 0
e2e/suites/provider/cases/aws/parameterstore/parameterstore.go

@@ -33,6 +33,7 @@ var _ = Describe("[aws] ", Label("aws", "parameterstore"), func() {
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.JSONDataFromSync(f)),
 		Entry(common.JSONDataFromSync(f)),
+		Entry(common.JSONDataFromRewrite(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.DockerJSONConfig(f)),
 		Entry(common.DockerJSONConfig(f)),

+ 1 - 0
e2e/suites/provider/cases/aws/secretsmanager/secretsmanager.go

@@ -33,6 +33,7 @@ var _ = Describe("[aws] ", Label("aws", "secretsmanager"), func() {
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.JSONDataFromSync(f)),
 		Entry(common.JSONDataFromSync(f)),
+		Entry(common.JSONDataFromRewrite(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.DockerJSONConfig(f)),
 		Entry(common.DockerJSONConfig(f)),

+ 1 - 0
e2e/suites/provider/cases/azure/azure_secret.go

@@ -30,6 +30,7 @@ var _ = Describe("[azure]", Label("azure", "keyvault", "secret"), func() {
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.JSONDataFromSync(f)),
 		Entry(common.JSONDataFromSync(f)),
+		Entry(common.JSONDataFromRewrite(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.DockerJSONConfig(f)),
 		Entry(common.DockerJSONConfig(f)),

+ 37 - 0
e2e/suites/provider/cases/common/common.go

@@ -291,6 +291,43 @@ func JSONDataFromSync(f *framework.Framework) (string, func(*framework.TestCase)
 	}
 	}
 }
 }
 
 
+// This case creates one secret with json values and syncs them using a single .Spec.DataFrom block.
+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")
+		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},
+		}
+		tc.ExpectedSecret = &v1.Secret{
+			Type: v1.SecretTypeOpaque,
+			Data: map[string][]byte{
+				"my_username": []byte(targetSecretValue1),
+				"my_address":  []byte(targetSecretValue2),
+			},
+		}
+		tc.ExternalSecret.Spec.DataFrom = []esv1beta1.ExternalSecretDataFromRemoteRef{
+			{
+				Extract: &esv1beta1.ExternalSecretDataRemoteRef{
+					Key: secretKey1,
+				},
+				Rewrite: []esv1beta1.ExternalSecretRewrite{
+					{
+						Regexp: &esv1beta1.ExternalSecretRewriteRegexp{
+							Source: "(.*)",
+							Target: "my_$1",
+						},
+					},
+				},
+			},
+		}
+	}
+}
+
 // This case creates a secret with a nested json value. It is synced into two secrets.
 // This case creates a secret with a nested json value. It is synced into two secrets.
 // The values from the nested data are extracted using gjson.
 // The values from the nested data are extracted using gjson.
 // not supported by: vault.
 // not supported by: vault.

+ 50 - 2
e2e/suites/provider/cases/common/find_by_name.go

@@ -21,6 +21,10 @@ import (
 	"github.com/external-secrets/external-secrets/e2e/framework"
 	"github.com/external-secrets/external-secrets/e2e/framework"
 )
 )
 
 
+const (
+	findValue = "{\"foo1\":\"foo1-val\"}"
+)
+
 // This case creates multiple secrets with simple key/value pairs and syncs them using multiple .Spec.Data blocks.
 // This case creates multiple secrets with simple key/value pairs and syncs them using multiple .Spec.Data blocks.
 func FindByName(f *framework.Framework) (string, func(*framework.TestCase)) {
 func FindByName(f *framework.Framework) (string, func(*framework.TestCase)) {
 	return "[common] should find secrets by name using .DataFrom[]", func(tc *framework.TestCase) {
 	return "[common] should find secrets by name using .DataFrom[]", func(tc *framework.TestCase) {
@@ -28,7 +32,7 @@ func FindByName(f *framework.Framework) (string, func(*framework.TestCase)) {
 		secretKeyOne := fmt.Sprintf(namePrefix, f.Namespace.Name, "one")
 		secretKeyOne := fmt.Sprintf(namePrefix, f.Namespace.Name, "one")
 		secretKeyTwo := fmt.Sprintf(namePrefix, f.Namespace.Name, "two")
 		secretKeyTwo := fmt.Sprintf(namePrefix, f.Namespace.Name, "two")
 		secretKeyThree := fmt.Sprintf(namePrefix, f.Namespace.Name, "three")
 		secretKeyThree := fmt.Sprintf(namePrefix, f.Namespace.Name, "three")
-		secretValue := "{\"foo1\":\"foo1-val\"}"
+		secretValue := findValue
 		tc.Secrets = map[string]framework.SecretEntry{
 		tc.Secrets = map[string]framework.SecretEntry{
 			secretKeyOne:   {Value: secretValue},
 			secretKeyOne:   {Value: secretValue},
 			secretKeyTwo:   {Value: secretValue},
 			secretKeyTwo:   {Value: secretValue},
@@ -54,12 +58,56 @@ func FindByName(f *framework.Framework) (string, func(*framework.TestCase)) {
 	}
 	}
 }
 }
 
 
+// This case creates multiple secrets with simple key/value pairs and syncs them using multiple .Spec.Data blocks.
+func FindByNameAndRewrite(f *framework.Framework) (string, func(*framework.TestCase)) {
+	return "[common] should find and rewrite secrets by name using .DataFrom[]", func(tc *framework.TestCase) {
+		const namePrefix = "e2e_find_and_rewrite_%s_%s"
+		secretKeyOne := fmt.Sprintf(namePrefix, f.Namespace.Name, "one")
+		secretKeyTwo := fmt.Sprintf(namePrefix, f.Namespace.Name, "two")
+		secretKeyThree := fmt.Sprintf(namePrefix, f.Namespace.Name, "three")
+		expectedKeyOne := fmt.Sprintf("%s_%s", f.Namespace.Name, "one")
+		expectedKeyTwo := fmt.Sprintf("%s_%s", f.Namespace.Name, "two")
+		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},
+		}
+		tc.ExpectedSecret = &v1.Secret{
+			Type: v1.SecretTypeOpaque,
+			Data: map[string][]byte{
+				expectedKeyOne:   []byte(secretValue),
+				expectedKeyTwo:   []byte(secretValue),
+				expectedKeyThree: []byte(secretValue),
+			},
+		}
+		tc.ExternalSecret.Spec.DataFrom = []esapi.ExternalSecretDataFromRemoteRef{
+			{
+				Find: &esapi.ExternalSecretFind{
+					Name: &esapi.FindName{
+						RegExp: fmt.Sprintf("e2e_find_and_rewrite_%s.+", f.Namespace.Name),
+					},
+				},
+				Rewrite: []esapi.ExternalSecretRewrite{
+					{
+						Regexp: &esapi.ExternalSecretRewriteRegexp{
+							Source: "e2e_find_and_rewrite_(.*)",
+							Target: "$1",
+						},
+					},
+				},
+			},
+		}
+	}
+}
+
 func FindByNameWithPath(f *framework.Framework) (string, func(*framework.TestCase)) {
 func FindByNameWithPath(f *framework.Framework) (string, func(*framework.TestCase)) {
 	return "[common] should find secrets by name with path", func(tc *framework.TestCase) {
 	return "[common] should find secrets by name with path", func(tc *framework.TestCase) {
 		secretKeyOne := fmt.Sprintf("e2e-find-name-%s-one", f.Namespace.Name)
 		secretKeyOne := fmt.Sprintf("e2e-find-name-%s-one", f.Namespace.Name)
 		secretKeyTwo := fmt.Sprintf("%s-two", f.Namespace.Name)
 		secretKeyTwo := fmt.Sprintf("%s-two", f.Namespace.Name)
 		secretKeythree := fmt.Sprintf("%s-three", f.Namespace.Name)
 		secretKeythree := fmt.Sprintf("%s-three", f.Namespace.Name)
-		secretValue := "{\"foo1\":\"foo1-val\"}"
+		secretValue := findValue
 		tc.Secrets = map[string]framework.SecretEntry{
 		tc.Secrets = map[string]framework.SecretEntry{
 			secretKeyOne:   {Value: secretValue},
 			secretKeyOne:   {Value: secretValue},
 			secretKeyTwo:   {Value: secretValue},
 			secretKeyTwo:   {Value: secretValue},

+ 2 - 0
e2e/suites/provider/cases/gcp/gcp.go

@@ -38,6 +38,7 @@ var _ = Describe("[gcp]", Label("gcp", "secretsmanager"), func() {
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataFromSync(f)),
 		Entry(common.JSONDataFromSync(f)),
+		Entry(common.JSONDataFromRewrite(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.DockerJSONConfig(f)),
 		Entry(common.DockerJSONConfig(f)),
@@ -47,6 +48,7 @@ var _ = Describe("[gcp]", Label("gcp", "secretsmanager"), func() {
 		Entry(common.SyncWithoutTargetName(f)),
 		Entry(common.SyncWithoutTargetName(f)),
 		Entry(common.JSONDataWithoutTargetName(f)),
 		Entry(common.JSONDataWithoutTargetName(f)),
 		Entry(common.FindByName(f)),
 		Entry(common.FindByName(f)),
+		Entry(common.FindByNameAndRewrite(f)),
 		Entry(common.FindByNameWithPath(f)),
 		Entry(common.FindByNameWithPath(f)),
 		Entry(common.FindByTag(f)),
 		Entry(common.FindByTag(f)),
 		Entry(common.FindByTagWithPath(f)),
 		Entry(common.FindByTagWithPath(f)),

+ 1 - 0
e2e/suites/provider/cases/gitlab/gitlab.go

@@ -34,6 +34,7 @@ var _ = Describe("[gitlab]", Label("gitlab"), func() {
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataFromSync(f)),
 		Entry(common.JSONDataFromSync(f)),
+		Entry(common.JSONDataFromRewrite(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.SyncWithoutTargetName(f)),
 		Entry(common.SyncWithoutTargetName(f)),

+ 1 - 0
e2e/suites/provider/cases/kubernetes/kubernetes.go

@@ -41,6 +41,7 @@ var _ = Describe("[kubernetes] ", Label("kubernetes"), func() {
 		Entry(common.DataPropertyDockerconfigJSON(f)),
 		Entry(common.DataPropertyDockerconfigJSON(f)),
 		Entry(common.SSHKeySyncDataProperty(f)),
 		Entry(common.SSHKeySyncDataProperty(f)),
 		Entry(common.JSONDataFromSync(f)),
 		Entry(common.JSONDataFromSync(f)),
+		Entry(common.JSONDataFromRewrite(f)),
 		Entry(FindByTag(f)),
 		Entry(FindByTag(f)),
 		Entry(FindByName(f)),
 		Entry(FindByName(f)),
 
 

+ 1 - 0
e2e/suites/provider/cases/oracle/oracle.go

@@ -29,6 +29,7 @@ var _ = Describe("[oracle]", Label("oracle"), func() {
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.SimpleDataSync(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.NestedJSONWithGJSON(f)),
 		Entry(common.JSONDataFromSync(f)),
 		Entry(common.JSONDataFromSync(f)),
+		Entry(common.JSONDataFromRewrite(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataWithProperty(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.JSONDataWithTemplate(f)),
 		Entry(common.DockerJSONConfig(f)),
 		Entry(common.DockerJSONConfig(f)),

+ 12 - 0
e2e/suites/provider/cases/vault/vault.go

@@ -43,7 +43,9 @@ var _ = Describe("[vault]", Label("vault"), func() {
 		framework.TableFunc(f, prov),
 		framework.TableFunc(f, prov),
 		// uses token auth
 		// uses token auth
 		framework.Compose(withTokenAuth, f, common.FindByName, useTokenAuth),
 		framework.Compose(withTokenAuth, f, common.FindByName, useTokenAuth),
+		framework.Compose(withTokenAuth, f, common.FindByNameAndRewrite, useTokenAuth),
 		framework.Compose(withTokenAuth, f, common.JSONDataFromSync, useTokenAuth),
 		framework.Compose(withTokenAuth, f, common.JSONDataFromSync, useTokenAuth),
+		framework.Compose(withTokenAuth, f, common.JSONDataFromRewrite, useTokenAuth),
 		framework.Compose(withTokenAuth, f, common.JSONDataWithProperty, useTokenAuth),
 		framework.Compose(withTokenAuth, f, common.JSONDataWithProperty, useTokenAuth),
 		framework.Compose(withTokenAuth, f, common.JSONDataWithTemplate, useTokenAuth),
 		framework.Compose(withTokenAuth, f, common.JSONDataWithTemplate, useTokenAuth),
 		framework.Compose(withTokenAuth, f, common.DataPropertyDockerconfigJSON, useTokenAuth),
 		framework.Compose(withTokenAuth, f, common.DataPropertyDockerconfigJSON, useTokenAuth),
@@ -52,40 +54,50 @@ var _ = Describe("[vault]", Label("vault"), func() {
 		framework.Compose(withTokenAuth, f, common.DecodingPolicySync, useTokenAuth),
 		framework.Compose(withTokenAuth, f, common.DecodingPolicySync, useTokenAuth),
 		// use cert auth
 		// use cert auth
 		framework.Compose(withCertAuth, f, common.FindByName, useCertAuth),
 		framework.Compose(withCertAuth, f, common.FindByName, useCertAuth),
+		framework.Compose(withCertAuth, f, common.FindByNameAndRewrite, useCertAuth),
 		framework.Compose(withCertAuth, f, common.JSONDataFromSync, useCertAuth),
 		framework.Compose(withCertAuth, f, common.JSONDataFromSync, useCertAuth),
+		framework.Compose(withCertAuth, f, common.JSONDataFromRewrite, useCertAuth),
 		framework.Compose(withCertAuth, f, common.JSONDataWithProperty, useCertAuth),
 		framework.Compose(withCertAuth, f, common.JSONDataWithProperty, useCertAuth),
 		framework.Compose(withCertAuth, f, common.JSONDataWithTemplate, useCertAuth),
 		framework.Compose(withCertAuth, f, common.JSONDataWithTemplate, useCertAuth),
 		framework.Compose(withCertAuth, f, common.DataPropertyDockerconfigJSON, useCertAuth),
 		framework.Compose(withCertAuth, f, common.DataPropertyDockerconfigJSON, useCertAuth),
 		framework.Compose(withCertAuth, f, common.JSONDataWithoutTargetName, useCertAuth),
 		framework.Compose(withCertAuth, f, common.JSONDataWithoutTargetName, useCertAuth),
 		// use approle auth
 		// use approle auth
 		framework.Compose(withApprole, f, common.FindByName, useApproleAuth),
 		framework.Compose(withApprole, f, common.FindByName, useApproleAuth),
+		framework.Compose(withApprole, f, common.FindByNameAndRewrite, useApproleAuth),
 		framework.Compose(withApprole, f, common.JSONDataFromSync, useApproleAuth),
 		framework.Compose(withApprole, f, common.JSONDataFromSync, useApproleAuth),
+		framework.Compose(withApprole, f, common.JSONDataFromRewrite, useApproleAuth),
 		framework.Compose(withApprole, f, common.JSONDataWithProperty, useApproleAuth),
 		framework.Compose(withApprole, f, common.JSONDataWithProperty, useApproleAuth),
 		framework.Compose(withApprole, f, common.JSONDataWithTemplate, useApproleAuth),
 		framework.Compose(withApprole, f, common.JSONDataWithTemplate, useApproleAuth),
 		framework.Compose(withApprole, f, common.DataPropertyDockerconfigJSON, useApproleAuth),
 		framework.Compose(withApprole, f, common.DataPropertyDockerconfigJSON, useApproleAuth),
 		framework.Compose(withApprole, f, common.JSONDataWithoutTargetName, useApproleAuth),
 		framework.Compose(withApprole, f, common.JSONDataWithoutTargetName, useApproleAuth),
 		// use v1 provider
 		// use v1 provider
 		framework.Compose(withV1, f, common.JSONDataFromSync, useV1Provider),
 		framework.Compose(withV1, f, common.JSONDataFromSync, useV1Provider),
+		framework.Compose(withV1, f, common.JSONDataFromRewrite, useV1Provider),
 		framework.Compose(withV1, f, common.JSONDataWithProperty, useV1Provider),
 		framework.Compose(withV1, f, common.JSONDataWithProperty, useV1Provider),
 		framework.Compose(withV1, f, common.JSONDataWithTemplate, useV1Provider),
 		framework.Compose(withV1, f, common.JSONDataWithTemplate, useV1Provider),
 		framework.Compose(withV1, f, common.DataPropertyDockerconfigJSON, useV1Provider),
 		framework.Compose(withV1, f, common.DataPropertyDockerconfigJSON, useV1Provider),
 		framework.Compose(withV1, f, common.JSONDataWithoutTargetName, useV1Provider),
 		framework.Compose(withV1, f, common.JSONDataWithoutTargetName, useV1Provider),
 		// use jwt provider
 		// use jwt provider
 		framework.Compose(withJWT, f, common.FindByName, useJWTProvider),
 		framework.Compose(withJWT, f, common.FindByName, useJWTProvider),
+		framework.Compose(withJWT, f, common.FindByNameAndRewrite, useJWTProvider),
 		framework.Compose(withJWT, f, common.JSONDataFromSync, useJWTProvider),
 		framework.Compose(withJWT, f, common.JSONDataFromSync, useJWTProvider),
+		framework.Compose(withJWT, f, common.JSONDataFromRewrite, useJWTProvider),
 		framework.Compose(withJWT, f, common.JSONDataWithProperty, useJWTProvider),
 		framework.Compose(withJWT, f, common.JSONDataWithProperty, useJWTProvider),
 		framework.Compose(withJWT, f, common.JSONDataWithTemplate, useJWTProvider),
 		framework.Compose(withJWT, f, common.JSONDataWithTemplate, useJWTProvider),
 		framework.Compose(withJWT, f, common.DataPropertyDockerconfigJSON, useJWTProvider),
 		framework.Compose(withJWT, f, common.DataPropertyDockerconfigJSON, useJWTProvider),
 		framework.Compose(withJWT, f, common.JSONDataWithoutTargetName, useJWTProvider),
 		framework.Compose(withJWT, f, common.JSONDataWithoutTargetName, useJWTProvider),
 		// use jwt k8s provider
 		// use jwt k8s provider
 		framework.Compose(withJWTK8s, f, common.JSONDataFromSync, useJWTK8sProvider),
 		framework.Compose(withJWTK8s, f, common.JSONDataFromSync, useJWTK8sProvider),
+		framework.Compose(withJWTK8s, f, common.JSONDataFromRewrite, useJWTK8sProvider),
 		framework.Compose(withJWTK8s, f, common.JSONDataWithProperty, useJWTK8sProvider),
 		framework.Compose(withJWTK8s, f, common.JSONDataWithProperty, useJWTK8sProvider),
 		framework.Compose(withJWTK8s, f, common.JSONDataWithTemplate, useJWTK8sProvider),
 		framework.Compose(withJWTK8s, f, common.JSONDataWithTemplate, useJWTK8sProvider),
 		framework.Compose(withJWTK8s, f, common.DataPropertyDockerconfigJSON, useJWTK8sProvider),
 		framework.Compose(withJWTK8s, f, common.DataPropertyDockerconfigJSON, useJWTK8sProvider),
 		framework.Compose(withJWTK8s, f, common.JSONDataWithoutTargetName, useJWTK8sProvider),
 		framework.Compose(withJWTK8s, f, common.JSONDataWithoutTargetName, useJWTK8sProvider),
 		// use kubernetes provider
 		// use kubernetes provider
 		framework.Compose(withK8s, f, common.FindByName, useKubernetesProvider),
 		framework.Compose(withK8s, f, common.FindByName, useKubernetesProvider),
+		framework.Compose(withK8s, f, common.FindByNameAndRewrite, useKubernetesProvider),
 		framework.Compose(withK8s, f, common.JSONDataFromSync, useKubernetesProvider),
 		framework.Compose(withK8s, f, common.JSONDataFromSync, useKubernetesProvider),
+		framework.Compose(withK8s, f, common.JSONDataFromRewrite, useKubernetesProvider),
 		framework.Compose(withK8s, f, common.JSONDataWithProperty, useKubernetesProvider),
 		framework.Compose(withK8s, f, common.JSONDataWithProperty, useKubernetesProvider),
 		framework.Compose(withK8s, f, common.JSONDataWithTemplate, useKubernetesProvider),
 		framework.Compose(withK8s, f, common.JSONDataWithTemplate, useKubernetesProvider),
 		framework.Compose(withK8s, f, common.DataPropertyDockerconfigJSON, useKubernetesProvider),
 		framework.Compose(withK8s, f, common.DataPropertyDockerconfigJSON, useKubernetesProvider),

+ 17 - 17
go.mod

@@ -35,12 +35,12 @@ replace (
 require (
 require (
 	cloud.google.com/go v0.102.0 // indirect
 	cloud.google.com/go v0.102.0 // indirect
 	cloud.google.com/go/iam v0.3.0
 	cloud.google.com/go/iam v0.3.0
-	cloud.google.com/go/secretmanager v1.4.0
+	cloud.google.com/go/secretmanager v1.5.0
 	github.com/Azure/azure-sdk-for-go v66.0.0+incompatible
 	github.com/Azure/azure-sdk-for-go v66.0.0+incompatible
-	github.com/Azure/go-autorest/autorest v0.11.27
+	github.com/Azure/go-autorest/autorest v0.11.28
 	github.com/Azure/go-autorest/autorest/adal v0.9.20
 	github.com/Azure/go-autorest/autorest/adal v0.9.20
 	github.com/Azure/go-autorest/autorest/azure/auth v0.5.11
 	github.com/Azure/go-autorest/autorest/azure/auth v0.5.11
-	github.com/AzureAD/microsoft-authentication-library-for-go v0.5.2
+	github.com/AzureAD/microsoft-authentication-library-for-go v0.5.3
 	github.com/IBM/go-sdk-core/v5 v5.10.1
 	github.com/IBM/go-sdk-core/v5 v5.10.1
 	github.com/IBM/secrets-manager-go-sdk v1.0.44
 	github.com/IBM/secrets-manager-go-sdk v1.0.44
 	github.com/Masterminds/goutils v1.1.1 // indirect
 	github.com/Masterminds/goutils v1.1.1 // indirect
@@ -48,10 +48,10 @@ require (
 	github.com/PaesslerAG/jsonpath v0.1.1
 	github.com/PaesslerAG/jsonpath v0.1.1
 	github.com/ahmetb/gen-crd-api-reference-docs v0.3.0
 	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-cloud-id v0.3.4
-	github.com/akeylesslabs/akeyless-go/v2 v2.16.8
+	github.com/akeylesslabs/akeyless-go/v2 v2.17.0
 	github.com/aliyun/alibaba-cloud-sdk-go v1.61.1673
 	github.com/aliyun/alibaba-cloud-sdk-go v1.61.1673
 	github.com/aws/aws-sdk-go v1.44.52
 	github.com/aws/aws-sdk-go v1.44.52
-	github.com/crossplane/crossplane-runtime v0.16.0
+	github.com/crossplane/crossplane-runtime v0.17.0
 	github.com/go-logr/logr v1.2.3
 	github.com/go-logr/logr v1.2.3
 	github.com/go-test/deep v1.0.4 // indirect
 	github.com/go-test/deep v1.0.4 // indirect
 	github.com/golang-jwt/jwt/v4 v4.4.2
 	github.com/golang-jwt/jwt/v4 v4.4.2
@@ -60,28 +60,28 @@ require (
 	github.com/googleapis/gax-go/v2 v2.4.0
 	github.com/googleapis/gax-go/v2 v2.4.0
 	github.com/hashicorp/vault/api v1.7.2
 	github.com/hashicorp/vault/api v1.7.2
 	github.com/hashicorp/vault/api/auth/approle v0.2.0
 	github.com/hashicorp/vault/api/auth/approle v0.2.0
-	github.com/hashicorp/vault/api/auth/kubernetes v0.1.0
+	github.com/hashicorp/vault/api/auth/kubernetes v0.2.0
 	github.com/hashicorp/vault/api/auth/ldap v0.1.0
 	github.com/hashicorp/vault/api/auth/ldap v0.1.0
 	github.com/huandu/xstrings v1.3.2 // indirect
 	github.com/huandu/xstrings v1.3.2 // indirect
 	github.com/lestrrat-go/jwx v1.2.25
 	github.com/lestrrat-go/jwx v1.2.25
 	github.com/onsi/ginkgo/v2 v2.1.4
 	github.com/onsi/ginkgo/v2 v2.1.4
-	github.com/onsi/gomega v1.19.0
+	github.com/onsi/gomega v1.20.0
 	github.com/oracle/oci-go-sdk/v56 v56.1.0
 	github.com/oracle/oci-go-sdk/v56 v56.1.0
 	github.com/prometheus/client_golang v1.12.2
 	github.com/prometheus/client_golang v1.12.2
 	github.com/prometheus/client_model v0.2.0
 	github.com/prometheus/client_model v0.2.0
-	github.com/spf13/cobra v1.4.0
+	github.com/spf13/cobra v1.5.0
 	github.com/stretchr/testify v1.8.0
 	github.com/stretchr/testify v1.8.0
 	github.com/tidwall/gjson v1.14.1
 	github.com/tidwall/gjson v1.14.1
-	github.com/xanzy/go-gitlab v0.68.2
+	github.com/xanzy/go-gitlab v0.70.0
 	github.com/yandex-cloud/go-genproto v0.0.0-20220314102905-1acaee8ca7eb
 	github.com/yandex-cloud/go-genproto v0.0.0-20220314102905-1acaee8ca7eb
 	github.com/yandex-cloud/go-sdk v0.0.0-20220314105123-d0c2a928feb6
 	github.com/yandex-cloud/go-sdk v0.0.0-20220314105123-d0c2a928feb6
 	github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a
 	github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a
 	go.uber.org/zap v1.21.0
 	go.uber.org/zap v1.21.0
-	golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
+	golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
 	golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2
 	golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2
-	google.golang.org/api v0.87.0
+	google.golang.org/api v0.88.0
 	google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f
 	google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f
-	google.golang.org/grpc v1.47.0
+	google.golang.org/grpc v1.48.0
 	gopkg.in/yaml.v3 v3.0.1
 	gopkg.in/yaml.v3 v3.0.1
 	grpc.go4.org v0.0.0-20170609214715-11d0a25b4919
 	grpc.go4.org v0.0.0-20170609214715-11d0a25b4919
 	k8s.io/api v0.24.0
 	k8s.io/api v0.24.0
@@ -90,17 +90,17 @@ require (
 	k8s.io/client-go v0.23.5
 	k8s.io/client-go v0.23.5
 	k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
 	k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
 	sigs.k8s.io/controller-runtime v0.11.2
 	sigs.k8s.io/controller-runtime v0.11.2
-	sigs.k8s.io/controller-tools v0.9.0
-	software.sslmate.com/src/go-pkcs12 v0.2.0
+	sigs.k8s.io/controller-tools v0.9.2
+	software.sslmate.com/src/go-pkcs12 v0.0.0-20210415151418-c5206de65a78
 )
 )
 
 
-require github.com/1Password/connect-sdk-go v1.4.0
+require github.com/1Password/connect-sdk-go v1.5.0
 
 
 require (
 require (
 	github.com/argoproj/argo-cd/v2 v2.4.6
 	github.com/argoproj/argo-cd/v2 v2.4.6
-	github.com/fluxcd/helm-controller/api v0.22.1
+	github.com/fluxcd/helm-controller/api v0.22.2
 	github.com/fluxcd/pkg/apis/meta v0.14.2
 	github.com/fluxcd/pkg/apis/meta v0.14.2
-	github.com/fluxcd/source-controller/api v0.25.10
+	github.com/fluxcd/source-controller/api v0.25.11
 	github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0
 	github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0
 	gotest.tools/v3 v3.0.3
 	gotest.tools/v3 v3.0.3
 	sigs.k8s.io/yaml v1.3.0
 	sigs.k8s.io/yaml v1.3.0

+ 45 - 38
go.sum

@@ -57,8 +57,8 @@ cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2k
 cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
 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=
 cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
 cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
 cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
-cloud.google.com/go/secretmanager v1.4.0 h1:Cl+kDYvKHjPQ1l2DZDr2FG/cXUzNGCZkh05BARgddo8=
-cloud.google.com/go/secretmanager v1.4.0/go.mod h1:h2VZz7Svt1W9/YVl7mfcX9LddvS6SOLOvMoOXBhYT1k=
+cloud.google.com/go/secretmanager v1.5.0 h1:XdbW+Fx5amsRzjHeFbDAQI2v2VUkSl3BWEgkQD6z8hY=
+cloud.google.com/go/secretmanager v1.5.0/go.mod h1:5C9kM+RwSpkURNovKySkNvGQLUaOgyoR5W0RUx2SyHQ=
 cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
 cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
 cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
 cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
 cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
 cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
@@ -70,8 +70,8 @@ code.gitea.io/gitea-vet v0.2.1/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFj
 code.gitea.io/sdk/gitea v0.15.1/go.mod h1:klY2LVI3s3NChzIk/MzMn7G1FHrfU7qd63iSMVoHRBA=
 code.gitea.io/sdk/gitea v0.15.1/go.mod h1:klY2LVI3s3NChzIk/MzMn7G1FHrfU7qd63iSMVoHRBA=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 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=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-github.com/1Password/connect-sdk-go v1.4.0 h1:c1cR22z69E634ZxEhjsBI08FNEcDBuM57IKMFDk04aM=
-github.com/1Password/connect-sdk-go v1.4.0/go.mod h1:ADZd9XFWwbBcnAayv7hVm9LTF0WkyoJ37jVA6BRtqzE=
+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 v55.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
 github.com/Azure/azure-sdk-for-go v55.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
 github.com/Azure/azure-sdk-for-go v66.0.0+incompatible h1:bmmC38SlE8/E81nNADlgmVGurPWMHDX2YNXVQMrBpEE=
 github.com/Azure/azure-sdk-for-go v66.0.0+incompatible h1:bmmC38SlE8/E81nNADlgmVGurPWMHDX2YNXVQMrBpEE=
 github.com/Azure/azure-sdk-for-go v66.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
 github.com/Azure/azure-sdk-for-go v66.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
@@ -83,8 +83,8 @@ github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK
 github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
 github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
 github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc=
 github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc=
-github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A=
-github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U=
+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.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
 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.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
 github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg=
 github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg=
@@ -107,17 +107,15 @@ 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/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 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
 github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
 github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
-github.com/AzureAD/microsoft-authentication-library-for-go v0.5.2 h1:BGX4OiGP9htYSd6M3pAZctcUUSruhIAUVkv2X0Cn9yE=
-github.com/AzureAD/microsoft-authentication-library-for-go v0.5.2/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4=
+github.com/AzureAD/microsoft-authentication-library-for-go v0.5.3 h1:TsFCaaF5tR4XN8b4zLVl/J4qMb0nf80Q4CXcpXDNJDY=
+github.com/AzureAD/microsoft-authentication-library-for-go v0.5.3/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 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/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
 github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
 github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
 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/GoogleCloudPlatform/k8s-cloud-provider v1.16.1-0.20210702024009-ea6160c1d0e3/go.mod h1:8XasY4ymP2V/tn2OOV9ZadmiTE1FIB/h3W+yNlPttKw=
-github.com/HdrHistogram/hdrhistogram-go v1.0.1 h1:GX8GAYDuhlFQnI2fRDHQhTlkHMz8bEn0jTI6LJU0mpw=
-github.com/HdrHistogram/hdrhistogram-go v1.0.1 h1:GX8GAYDuhlFQnI2fRDHQhTlkHMz8bEn0jTI6LJU0mpw=
-github.com/HdrHistogram/hdrhistogram-go v1.0.1/go.mod h1:BWJ+nMSHY3L41Zj7CA3uXnloDp7xxV0YvstAE7nKTaM=
-github.com/HdrHistogram/hdrhistogram-go v1.0.1/go.mod h1:BWJ+nMSHY3L41Zj7CA3uXnloDp7xxV0YvstAE7nKTaM=
+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.9.5/go.mod h1:YlOwV9LeuclmT/qi/LAK2AsobbAP42veV0j68/rlZsE=
 github.com/IBM/go-sdk-core/v5 v5.9.5/go.mod h1:YlOwV9LeuclmT/qi/LAK2AsobbAP42veV0j68/rlZsE=
 github.com/IBM/go-sdk-core/v5 v5.10.1 h1:IEpjDJyB7okrC6bJ7fPZqBiOv+16VichT6kZXAz9bbQ=
 github.com/IBM/go-sdk-core/v5 v5.10.1 h1:IEpjDJyB7okrC6bJ7fPZqBiOv+16VichT6kZXAz9bbQ=
 github.com/IBM/go-sdk-core/v5 v5.10.1/go.mod h1:u/33BzPy8sthgEhSeBnf6/kPCqwvC9VKw5byfqQfbe0=
 github.com/IBM/go-sdk-core/v5 v5.10.1/go.mod h1:u/33BzPy8sthgEhSeBnf6/kPCqwvC9VKw5byfqQfbe0=
@@ -175,8 +173,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/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 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-cloud-id v0.3.4/go.mod h1:As/RomC2w/fa3y+yHRlVHPmkbP+zrKBFRow41y5dk+E=
-github.com/akeylesslabs/akeyless-go/v2 v2.16.8 h1:tjcaT3BHDsSmypDVNCQXDUj/lK0JB9DJKsf8AASYBXU=
-github.com/akeylesslabs/akeyless-go/v2 v2.16.8/go.mod h1:uOdXD49NCCe4rexeSc2aBU5Qv4KZgJE6YlbtYalvb+I=
+github.com/akeylesslabs/akeyless-go/v2 v2.17.0 h1:dC257qIL63tuqKCqDLCKblwudwh7gimm4/GrkXUHchc=
+github.com/akeylesslabs/akeyless-go/v2 v2.17.0/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-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/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-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -335,12 +333,13 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
 github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
 github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/crossplane/crossplane-runtime v0.16.0 h1:NstJdHeK3C+u3By0vQjOG1Y6+v53JYOy00IgCL9GHAw=
-github.com/crossplane/crossplane-runtime v0.16.0/go.mod h1:IPT3HTsovwmbw3i+SdsOyaC3r3b7TW+otBMmZsHLnSU=
+github.com/crossplane/crossplane-runtime v0.17.0 h1:gt2JcOYcVBw/luQToq2hUkoersL12ICuV0YzKI5lyCs=
+github.com/crossplane/crossplane-runtime v0.17.0/go.mod h1:IPT3HTsovwmbw3i+SdsOyaC3r3b7TW+otBMmZsHLnSU=
 github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
 github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
 github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -414,8 +413,8 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
 github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
 github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
 github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/flosch/pongo2 v0.0.0-20181225140029-79872a7b2769/go.mod h1:tbAXHifHQWNSpWbiJHpJTZH5fi3XHhDMdP//vuz9WS4=
 github.com/flosch/pongo2 v0.0.0-20181225140029-79872a7b2769/go.mod h1:tbAXHifHQWNSpWbiJHpJTZH5fi3XHhDMdP//vuz9WS4=
-github.com/fluxcd/helm-controller/api v0.22.1 h1:J+i6AZMj0SCuQxcpHmyf1qmPdgDKP0nTkyS4/oLHx0M=
-github.com/fluxcd/helm-controller/api v0.22.1/go.mod h1:2xuHOYjbRv86ekTYkF7VzTwu5hEHYawrdi7FZrvpr4g=
+github.com/fluxcd/helm-controller/api v0.22.2 h1:nh0GZBsUE0gNzm4PmPa4aOoqYlbZbpGt2pcIL9S2184=
+github.com/fluxcd/helm-controller/api v0.22.2/go.mod h1:GfD9TFgLyn81VgwZN1yM47/aUdz0SwTSyRAGmC8xZ+c=
 github.com/fluxcd/pkg/apis/acl v0.0.3 h1:Lw0ZHdpnO4G7Zy9KjrzwwBmDZQuy4qEjaU/RvA6k1lc=
 github.com/fluxcd/pkg/apis/acl v0.0.3 h1:Lw0ZHdpnO4G7Zy9KjrzwwBmDZQuy4qEjaU/RvA6k1lc=
 github.com/fluxcd/pkg/apis/acl v0.0.3/go.mod h1:XPts6lRJ9C9fIF9xVWofmQwftvhY25n1ps7W9xw0XLU=
 github.com/fluxcd/pkg/apis/acl v0.0.3/go.mod h1:XPts6lRJ9C9fIF9xVWofmQwftvhY25n1ps7W9xw0XLU=
 github.com/fluxcd/pkg/apis/kustomize v0.4.1 h1:YgIF9TJ23pH66W/gYlEu+DeH1pU3tS4xYlRc5AQzk58=
 github.com/fluxcd/pkg/apis/kustomize v0.4.1 h1:YgIF9TJ23pH66W/gYlEu+DeH1pU3tS4xYlRc5AQzk58=
@@ -423,8 +422,8 @@ github.com/fluxcd/pkg/apis/kustomize v0.4.1/go.mod h1:U9rfSgDHaQd74PgPKt9DprtuzT
 github.com/fluxcd/pkg/apis/meta v0.14.1/go.mod h1:1uJkTJGSZWrZxL5PFpx1IxGLrFmT1Cd0C2fFWrbv77I=
 github.com/fluxcd/pkg/apis/meta v0.14.1/go.mod h1:1uJkTJGSZWrZxL5PFpx1IxGLrFmT1Cd0C2fFWrbv77I=
 github.com/fluxcd/pkg/apis/meta v0.14.2 h1:/Hf7I/Vz01vv3m7Qx7DtQvrzAL1oVt0MJcLb/I1Y1HE=
 github.com/fluxcd/pkg/apis/meta v0.14.2 h1:/Hf7I/Vz01vv3m7Qx7DtQvrzAL1oVt0MJcLb/I1Y1HE=
 github.com/fluxcd/pkg/apis/meta v0.14.2/go.mod h1:ijZ61VG/8T3U17gj0aFL3fdtZL+mulD6V8VrLLUCAgM=
 github.com/fluxcd/pkg/apis/meta v0.14.2/go.mod h1:ijZ61VG/8T3U17gj0aFL3fdtZL+mulD6V8VrLLUCAgM=
-github.com/fluxcd/source-controller/api v0.25.10 h1:nwOB6Awy6mLlysEHfmqmk6Ek5yebYQ8kYq0lv+bSKb8=
-github.com/fluxcd/source-controller/api v0.25.10/go.mod h1:5kihSWjg+gIXLPTTXbe6AnY+g+iDmP+CY4g6nFqublc=
+github.com/fluxcd/source-controller/api v0.25.11 h1:1YbH5vlQ1k96tbRKTdQHCBsBVMgpp/QaRpKG/r29koQ=
+github.com/fluxcd/source-controller/api v0.25.11/go.mod h1:5kihSWjg+gIXLPTTXbe6AnY+g+iDmP+CY4g6nFqublc=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
 github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
 github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
@@ -824,14 +823,13 @@ github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOn
 github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
 github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
 github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
 github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
 github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
 github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
-github.com/hashicorp/vault/api v1.3.0/go.mod h1:EabNQLI0VWbWoGlA+oBLC8PXmR9D60aUVgQGvangFWQ=
 github.com/hashicorp/vault/api v1.3.1/go.mod h1:QeJoWxMFt+MsuWcYhmwRLwKEXrjwAFFywzhptMsTIUw=
 github.com/hashicorp/vault/api v1.3.1/go.mod h1:QeJoWxMFt+MsuWcYhmwRLwKEXrjwAFFywzhptMsTIUw=
 github.com/hashicorp/vault/api v1.7.2 h1:kawHE7s/4xwrdKbkmwQi0wYaIeUhk5ueek7ljuezCVQ=
 github.com/hashicorp/vault/api v1.7.2 h1:kawHE7s/4xwrdKbkmwQi0wYaIeUhk5ueek7ljuezCVQ=
 github.com/hashicorp/vault/api v1.7.2/go.mod h1:xbfA+1AvxFseDzxxdWaL0uO99n1+tndus4GCrtouy0M=
 github.com/hashicorp/vault/api v1.7.2/go.mod h1:xbfA+1AvxFseDzxxdWaL0uO99n1+tndus4GCrtouy0M=
 github.com/hashicorp/vault/api/auth/approle v0.2.0 h1:mdNYwDRp+tqvJmyfbkaHLLePGYDY27mOFtBZBb7va/I=
 github.com/hashicorp/vault/api/auth/approle v0.2.0 h1:mdNYwDRp+tqvJmyfbkaHLLePGYDY27mOFtBZBb7va/I=
 github.com/hashicorp/vault/api/auth/approle v0.2.0/go.mod h1:w4PwYaLJmGq0cMss0ZAV9b49vcrpB6SKxMMLUp4voR8=
 github.com/hashicorp/vault/api/auth/approle v0.2.0/go.mod h1:w4PwYaLJmGq0cMss0ZAV9b49vcrpB6SKxMMLUp4voR8=
-github.com/hashicorp/vault/api/auth/kubernetes v0.1.0 h1:6BtyahbF4aQp8gg3ww0A/oIoqzbhpNP1spXU3nHE0n0=
-github.com/hashicorp/vault/api/auth/kubernetes v0.1.0/go.mod h1:Pdgk78uIs0mgDOLvc3a+h/vYIT9rznw2sz+ucuH9024=
+github.com/hashicorp/vault/api/auth/kubernetes v0.2.0 h1:ScdzRAF8JZIdJYP4oprZKsIS4GSTCaTP4iG2JJlJDvA=
+github.com/hashicorp/vault/api/auth/kubernetes v0.2.0/go.mod h1:2BKADs9mwqAycDK/6tiHRh2sX0SPnC0DN4wHjJoAirw=
 github.com/hashicorp/vault/api/auth/ldap v0.1.0 h1:runn+BIRU6/QcGirhstoJIqO+plVuTN/zf401tbB5H0=
 github.com/hashicorp/vault/api/auth/ldap v0.1.0 h1:runn+BIRU6/QcGirhstoJIqO+plVuTN/zf401tbB5H0=
 github.com/hashicorp/vault/api/auth/ldap v0.1.0/go.mod h1:vl3YZyt+bRtTHvVqKWeOTCI5I40t31t0S48efipZq64=
 github.com/hashicorp/vault/api/auth/ldap v0.1.0/go.mod h1:vl3YZyt+bRtTHvVqKWeOTCI5I40t31t0S48efipZq64=
 github.com/hashicorp/vault/sdk v0.3.0/go.mod h1:aZ3fNuL5VNydQk8GcLJ2TV8YCRVvyaakYkhZRoVuhj0=
 github.com/hashicorp/vault/sdk v0.3.0/go.mod h1:aZ3fNuL5VNydQk8GcLJ2TV8YCRVvyaakYkhZRoVuhj0=
@@ -1120,8 +1118,9 @@ github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7
 github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
 github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
 github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
 github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
 github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
 github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
-github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
 github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
 github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
+github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q=
+github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
 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 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
@@ -1290,8 +1289,9 @@ github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHN
 github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
 github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
 github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
 github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
 github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4=
 github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4=
-github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
 github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
 github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
+github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
+github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
 github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
 github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@@ -1364,8 +1364,8 @@ github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV
 github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
 github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
 github.com/whilp/git-urls v0.0.0-20191001220047-6db9661140c0/go.mod h1:2rx5KE5FLD0HRfkkpyn8JwbVLBdhgeiOb2D2D9LLKM4=
 github.com/whilp/git-urls v0.0.0-20191001220047-6db9661140c0/go.mod h1:2rx5KE5FLD0HRfkkpyn8JwbVLBdhgeiOb2D2D9LLKM4=
 github.com/xanzy/go-gitlab v0.60.0/go.mod h1:F0QEXwmqiBUxCgJm8fE9S+1veX4XC9Z4cfaAbqwk4YM=
 github.com/xanzy/go-gitlab v0.60.0/go.mod h1:F0QEXwmqiBUxCgJm8fE9S+1veX4XC9Z4cfaAbqwk4YM=
-github.com/xanzy/go-gitlab v0.68.2 h1:bRVpa+czzpR2j2UV9oeJRU3SO40ieOHlgKlVwW0LRBw=
-github.com/xanzy/go-gitlab v0.68.2/go.mod h1:o4yExCtdaqlM8YGdDJWuZoBmfxBsmA9TPEjs9mx1UO4=
+github.com/xanzy/go-gitlab v0.70.0 h1:zJ8WukB5psMcfmQctHsiG/PyqLqLIdD05wCLwdPNEBg=
+github.com/xanzy/go-gitlab v0.70.0/go.mod h1:o4yExCtdaqlM8YGdDJWuZoBmfxBsmA9TPEjs9mx1UO4=
 github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
 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/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
 github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
 github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
@@ -1491,6 +1491,7 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
 golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
@@ -1498,10 +1499,10 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/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-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/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-20211215153901-e495a2d5b3d3/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-20220427172511-eb4f295cb31f/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-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
 golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
+golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 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-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1627,6 +1628,7 @@ golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su
 golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.0.0-20220621193019-9d032be2e588/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.0.0-20220621193019-9d032be2e588/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ=
 golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ=
 golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
@@ -1793,12 +1795,15 @@ golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/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-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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220624220833-87e55d714810 h1:rHZQSjJdAI4Xf5Qzeh2bBc5YJIkPFVM6oDtMFYmgws0=
 golang.org/x/sys v0.0.0-20220624220833-87e55d714810 h1:rHZQSjJdAI4Xf5Qzeh2bBc5YJIkPFVM6oDtMFYmgws0=
 golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
@@ -1917,6 +1922,7 @@ gomodules.xyz/notify v0.1.0/go.mod h1:wGy0vLXGpabCg0j9WbjzXf7pM7Khz11FqCLtBbTujP
 gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
 gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
 gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
 gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
 gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
 gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
+gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
 gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
 gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
 gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
 gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
 gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
 gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
@@ -1965,8 +1971,9 @@ google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69
 google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
 google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
 google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
 google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
 google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
 google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
-google.golang.org/api v0.87.0 h1:pUQVF/F+X7Tl1lo4LJoJf5BOpjtmINU80p9XpYTU2p4=
-google.golang.org/api v0.87.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
+google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g=
+google.golang.org/api v0.88.0 h1:MPwxQRqpyskYhr2iNyfsQ8R06eeyhe7UEuR30p136ZQ=
+google.golang.org/api v0.88.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
 google.golang.org/appengine v1.0.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.0.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 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.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -2061,7 +2068,6 @@ google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2
 google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
 google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
 google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
 google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
 google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
 google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
-google.golang.org/genproto v0.0.0-20220405205423-9d709892a2bf/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
 google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
 google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
 google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
 google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
 google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
 google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
@@ -2072,6 +2078,7 @@ google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP
 google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
 google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
 google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
 google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
 google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
 google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
+google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
 google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f h1:hJ/Y5SqPXbarffmAsApliUlcvMU+wScNGfyop4bZm8o=
 google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f h1:hJ/Y5SqPXbarffmAsApliUlcvMU+wScNGfyop4bZm8o=
 google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
 google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
 google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
 google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
@@ -2112,8 +2119,9 @@ google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ5
 google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
 google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
 google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
 google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
 google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
 google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
 google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
 google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
+google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w=
+google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 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-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@@ -2185,7 +2193,6 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
 gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20220512140231-539c8e751b99/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
 gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
@@ -2279,8 +2286,8 @@ sigs.k8s.io/controller-runtime v0.11.0/go.mod h1:KKwLiTooNGu+JmLZGn9Sl3Gjmfj66eM
 sigs.k8s.io/controller-runtime v0.11.2 h1:H5GTxQl0Mc9UjRJhORusqfJCIjBO8UtUxGggCwL1rLA=
 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/controller-runtime v0.11.2/go.mod h1:P6QCzrEjLaZGqHsfd+os7JQ+WFZhvB8MRFsn4dWF7O4=
 sigs.k8s.io/controller-tools v0.8.0/go.mod h1:qE2DXhVOiEq5ijmINcFbqi9GZrrUjzB1TuJU0xa6eoY=
 sigs.k8s.io/controller-tools v0.8.0/go.mod h1:qE2DXhVOiEq5ijmINcFbqi9GZrrUjzB1TuJU0xa6eoY=
-sigs.k8s.io/controller-tools v0.9.0 h1:b/vSEPpA8hiMiyzDfLbZdCn3hoAcy3/868OHhYtHY9w=
-sigs.k8s.io/controller-tools v0.9.0/go.mod h1:NUkn8FTV3Sad3wWpSK7dt/145qfuQ8CKJV6j4jHC5rM=
+sigs.k8s.io/controller-tools v0.9.2 h1:AkTE3QAdz9LS4iD3EJvHyYxBkg/g9fTbgiYsrcsFCcM=
+sigs.k8s.io/controller-tools v0.9.2/go.mod h1:NUkn8FTV3Sad3wWpSK7dt/145qfuQ8CKJV6j4jHC5rM=
 sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs=
 sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs=
 sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y=
 sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y=
 sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=
 sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=
@@ -2299,6 +2306,6 @@ sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
 sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
 sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
 sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
 sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
 sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
 sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
-software.sslmate.com/src/go-pkcs12 v0.2.0 h1:nlFkj7bTysH6VkC4fGphtjXRbezREPgrHuJG20hBGPE=
-software.sslmate.com/src/go-pkcs12 v0.2.0/go.mod h1:23rNcYsMabIc1otwLpTkCCPwUq6kQsTyowttG/as0kQ=
+software.sslmate.com/src/go-pkcs12 v0.0.0-20210415151418-c5206de65a78 h1:SqYE5+A2qvRhErbsXFfUEUmpWEKxxRSMgGLkvRAFOV4=
+software.sslmate.com/src/go-pkcs12 v0.0.0-20210415151418-c5206de65a78/go.mod h1:B7Wf0Ya4DHF9Yw+qfZuJijQYkWicqDa+79Ytmmq3Kjg=
 sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
 sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=

+ 7 - 0
hack/api-docs/mkdocs.yml

@@ -3,6 +3,7 @@ repo_url: https://github.com/external-secrets/external-secrets
 repo_name: External Secrets Operator
 repo_name: External Secrets Operator
 site_dir: ../../site
 site_dir: ../../site
 docs_dir: ../../docs
 docs_dir: ../../docs
+edit_uri: ./edit/main/docs/
 remote_branch: gh-pages
 remote_branch: gh-pages
 theme:
 theme:
   name: material
   name: material
@@ -18,6 +19,11 @@ plugins:
       lang: en
       lang: en
   - macros:
   - macros:
       include_dir: docs/snippets
       include_dir: docs/snippets
+copyright: |
+  &copy; 2022 The external-secrets Authors.<br/>
+  &copy; 2022 The Linux Foundation. All rights reserved.<br/><br/>
+  The Linux Foundation has registered trademarks and uses trademarks.<br/>
+  For a list of trademarks of The Linux Foundation, please see our <a href="https://www.linuxfoundation.org/trademark-usage/">Trademark Usage page</a>.
 extra:
 extra:
   version:
   version:
     provider: mike
     provider: mike
@@ -46,6 +52,7 @@ nav:
     - Getting Multiple Secrets: guides-getallsecrets.md
     - Getting Multiple Secrets: guides-getallsecrets.md
     - Multi Tenancy: guides-multi-tenancy.md
     - Multi Tenancy: guides-multi-tenancy.md
     - Metrics: guides-metrics.md
     - Metrics: guides-metrics.md
+    - Rewriting Keys: guides-datafrom-rewrite.md
     - Upgrading to v1beta1: guides-v1beta1.md
     - Upgrading to v1beta1: guides-v1beta1.md
     - Using Latest Image: guides-using-latest-image.md
     - Using Latest Image: guides-using-latest-image.md
   - Provider:
   - Provider:

+ 33 - 0
hack/crd.generate.sh

@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+BUNDLE_DIR="${1}"
+CRD_DIR="${2}"
+BUNDLE_YAML="${BUNDLE_DIR}/bundle.yaml"
+
+cd "${SCRIPT_DIR}"/../
+
+go run sigs.k8s.io/controller-tools/cmd/controller-gen \
+  object:headerFile="hack/boilerplate.go.txt" \
+  paths="./..."
+go run sigs.k8s.io/controller-tools/cmd/controller-gen crd \
+  paths="./..." \
+  output:crd:artifacts:config="${CRD_DIR}/bases"
+
+# Remove extra header lines in generated CRDs
+# This is needed for building the helm chart
+for f in "${CRD_DIR}"/bases/*.yaml; do
+  if [[ $f == *kustomization.yaml ]];
+  then
+      continue;
+  fi;
+  tail -n +2 < "$f" > "$f.bkp"
+  cp "$f.bkp" "$f"
+  rm "$f.bkp"
+done
+
+shopt -s extglob
+yq e \
+    '.spec.conversion.strategy = "Webhook" | .spec.conversion.webhook.conversionReviewVersions = ["v1"] | .spec.conversion.webhook.clientConfig.service.name = "kubernetes" | .spec.conversion.webhook.clientConfig.service.namespace = "default" |	.spec.conversion.webhook.clientConfig.service.path = "/convert"' \
+    "${CRD_DIR}"/bases/!(kustomization).yaml > "${BUNDLE_YAML}"

+ 35 - 0
hack/helm.generate.sh

@@ -0,0 +1,35 @@
+#!/usr/bin/env bash
+set -euo pipefail
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+BUNDLE_DIR="${1}"
+HELM_DIR="${2}"
+
+if [[ "$OSTYPE" == "darwin"* ]]; then
+  SEDPRG="gsed"
+else
+  SEDPRG="sed"
+fi
+
+cd "${SCRIPT_DIR}"/../
+
+# Split the generated bundle yaml file to inject control flags
+yq e -Ns "\"${HELM_DIR}/templates/crds/\" + .spec.names.singular" ${BUNDLE_DIR}/bundle.yaml
+
+# Add helm if statement for controlling the install of CRDs
+for i in "${HELM_DIR}"/templates/crds/*.yml; do
+  export CRDS_FLAG_NAME="create$(yq e '.spec.names.kind' $i)"
+  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"
+  else
+    echo "{{- if .Values.installCRDs }}" > "$i"
+  fi
+  cat "$i.bkp" >> "$i"
+  echo "{{- end }}" >> "$i"
+  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"
+  mv "$i" "${i%.yml}.yaml"
+done

+ 2 - 0
pkg/controllers/clusterexternalsecret/clusterexternalsecret_controller.go

@@ -16,6 +16,7 @@ package clusterexternalsecret
 
 
 import (
 import (
 	"context"
 	"context"
+	"sort"
 	"time"
 	"time"
 
 
 	"github.com/go-logr/logr"
 	"github.com/go-logr/logr"
@@ -130,6 +131,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
 	setFailedNamespaces(&clusterExternalSecret, failedNamespaces)
 	setFailedNamespaces(&clusterExternalSecret, failedNamespaces)
 
 
 	if len(provisionedNamespaces) > 0 {
 	if len(provisionedNamespaces) > 0 {
+		sort.Strings(provisionedNamespaces)
 		clusterExternalSecret.Status.ProvisionedNamespaces = provisionedNamespaces
 		clusterExternalSecret.Status.ProvisionedNamespaces = provisionedNamespaces
 	}
 	}
 
 

+ 26 - 5
pkg/controllers/externalsecret/externalsecret_controller.go

@@ -51,6 +51,8 @@ const (
 	errGetES                 = "could not get ExternalSecret"
 	errGetES                 = "could not get ExternalSecret"
 	errConvert               = "could not apply conversion strategy to keys: %v"
 	errConvert               = "could not apply conversion strategy to keys: %v"
 	errDecode                = "could not apply decoding strategy to %v[%d]: %v"
 	errDecode                = "could not apply decoding strategy to %v[%d]: %v"
+	errRewrite               = "could not rewrite spec.dataFrom[%d]: %v"
+	errInvalidKeys           = "secret keys from spec.dataFrom.%v[%d] can only have alphanumeric,'-', '_' or '.' characters. Convert them using rewrite (https://external-secrets.io/latest/guides-datafrom-rewrite)"
 	errUpdateSecret          = "could not update Secret"
 	errUpdateSecret          = "could not update Secret"
 	errPatchStatus           = "unable to patch status"
 	errPatchStatus           = "unable to patch status"
 	errGetSecretStore        = "could not get SecretStore %q, %w"
 	errGetSecretStore        = "could not get SecretStore %q, %w"
@@ -533,9 +535,20 @@ func (r *Reconciler) getProviderSecretData(ctx context.Context, providerClient e
 			if err != nil {
 			if err != nil {
 				return nil, err
 				return nil, err
 			}
 			}
-			secretMap, err = utils.ConvertKeys(remoteRef.Find.ConversionStrategy, secretMap)
+			secretMap, err = utils.RewriteMap(remoteRef.Rewrite, secretMap)
 			if err != nil {
 			if err != nil {
-				return nil, fmt.Errorf(errConvert, err)
+				return nil, fmt.Errorf(errRewrite, i, err)
+			}
+			if len(remoteRef.Rewrite) == 0 {
+				// ConversionStrategy is deprecated. Use RewriteMap instead.
+				r.recorder.Event(externalSecret, v1.EventTypeWarning, esv1beta1.ReasonDeprecated, fmt.Sprintf("dataFrom[%d].find.conversionStrategy=%v is deprecated and will be removed in further releases. Use dataFrom.rewrite instead", i, remoteRef.Find.ConversionStrategy))
+				secretMap, err = utils.ConvertKeys(remoteRef.Find.ConversionStrategy, secretMap)
+				if err != nil {
+					return nil, fmt.Errorf(errConvert, err)
+				}
+			}
+			if !utils.ValidateKeys(secretMap) {
+				return nil, fmt.Errorf(errInvalidKeys, "find", i)
 			}
 			}
 			secretMap, err = utils.DecodeMap(remoteRef.Find.DecodingStrategy, secretMap)
 			secretMap, err = utils.DecodeMap(remoteRef.Find.DecodingStrategy, secretMap)
 			if err != nil {
 			if err != nil {
@@ -550,16 +563,24 @@ func (r *Reconciler) getProviderSecretData(ctx context.Context, providerClient e
 			if err != nil {
 			if err != nil {
 				return nil, err
 				return nil, err
 			}
 			}
-			secretMap, err = utils.ConvertKeys(remoteRef.Extract.ConversionStrategy, secretMap)
+			secretMap, err = utils.RewriteMap(remoteRef.Rewrite, secretMap)
 			if err != nil {
 			if err != nil {
-				return nil, fmt.Errorf(errConvert, err)
+				return nil, fmt.Errorf(errRewrite, i, err)
+			}
+			if len(remoteRef.Rewrite) == 0 {
+				secretMap, err = utils.ConvertKeys(remoteRef.Extract.ConversionStrategy, secretMap)
+				if err != nil {
+					return nil, fmt.Errorf(errConvert, err)
+				}
+			}
+			if !utils.ValidateKeys(secretMap) {
+				return nil, fmt.Errorf(errInvalidKeys, "extract", i)
 			}
 			}
 			secretMap, err = utils.DecodeMap(remoteRef.Extract.DecodingStrategy, secretMap)
 			secretMap, err = utils.DecodeMap(remoteRef.Extract.DecodingStrategy, secretMap)
 			if err != nil {
 			if err != nil {
 				return nil, fmt.Errorf(errDecode, "spec.dataFrom", i, err)
 				return nil, fmt.Errorf(errDecode, "spec.dataFrom", i, err)
 			}
 			}
 		}
 		}
-
 		providerData = utils.MergeByteMap(providerData, secretMap)
 		providerData = utils.MergeByteMap(providerData, secretMap)
 	}
 	}
 
 

+ 168 - 0
pkg/controllers/externalsecret/externalsecret_controller_test.go

@@ -945,6 +945,139 @@ var _ = Describe("ExternalSecret controller", func() {
 		}
 		}
 	}
 	}
 
 
+	// with rewrite all keys from a dataFrom operation
+	// should be put with new rewriting into the secret
+	syncAndRewriteWithDataFrom := func(tc *testCase) {
+		tc.externalSecret.Spec.Data = nil
+		tc.externalSecret.Spec.DataFrom = []esv1beta1.ExternalSecretDataFromRemoteRef{
+			{
+				Extract: &esv1beta1.ExternalSecretDataRemoteRef{
+					Key: remoteKey,
+				},
+				Rewrite: []esv1beta1.ExternalSecretRewrite{{
+					Regexp: &esv1beta1.ExternalSecretRewriteRegexp{
+						Source: "(.*)",
+						Target: "new-$1",
+					},
+				}},
+			},
+			{
+				Extract: &esv1beta1.ExternalSecretDataRemoteRef{
+					Key: remoteKey,
+				},
+				Rewrite: []esv1beta1.ExternalSecretRewrite{{
+					Regexp: &esv1beta1.ExternalSecretRewriteRegexp{
+						Source: "(.*)",
+						Target: "old-$1",
+					},
+				}},
+			},
+		}
+		fakeProvider.WithGetSecretMap(map[string][]byte{
+			"foo": []byte(FooValue),
+			"bar": []byte(BarValue),
+		}, nil)
+		tc.checkSecret = func(es *esv1beta1.ExternalSecret, secret *v1.Secret) {
+			// check values
+			Expect(string(secret.Data["new-foo"])).To(Equal(FooValue))
+			Expect(string(secret.Data["new-bar"])).To(Equal(BarValue))
+			Expect(string(secret.Data["old-foo"])).To(Equal(FooValue))
+			Expect(string(secret.Data["old-bar"])).To(Equal(BarValue))
+		}
+	}
+	// with rewrite keys from dataFrom
+	// should error if keys are not compliant
+	invalidExtractKeysErrCondition := func(tc *testCase) {
+		tc.externalSecret.Spec.Data = nil
+		tc.externalSecret.Spec.DataFrom = []esv1beta1.ExternalSecretDataFromRemoteRef{
+			{
+				Extract: &esv1beta1.ExternalSecretDataRemoteRef{
+					Key: remoteKey,
+				},
+				Rewrite: []esv1beta1.ExternalSecretRewrite{{
+					Regexp: &esv1beta1.ExternalSecretRewriteRegexp{
+						Source: "(.*)",
+						Target: "$1",
+					},
+				}},
+			},
+		}
+		fakeProvider.WithGetSecretMap(map[string][]byte{
+			"foo/bar": []byte(FooValue),
+			"bar/foo": []byte(BarValue),
+		}, nil)
+		tc.checkCondition = func(es *esv1beta1.ExternalSecret) bool {
+			cond := GetExternalSecretCondition(es.Status, esv1beta1.ExternalSecretReady)
+			if cond == nil || cond.Status != v1.ConditionFalse || cond.Reason != esv1beta1.ConditionReasonSecretSyncedError {
+				return false
+			}
+			return true
+		}
+		tc.checkCondition = func(es *esv1beta1.ExternalSecret) bool {
+			cond := GetExternalSecretCondition(es.Status, esv1beta1.ExternalSecretReady)
+			if cond == nil || cond.Status != v1.ConditionFalse || cond.Reason != esv1beta1.ConditionReasonSecretSyncedError {
+				return false
+			}
+			return true
+		}
+		tc.checkExternalSecret = func(es *esv1beta1.ExternalSecret) {
+			Eventually(func() bool {
+				Expect(syncCallsError.WithLabelValues(ExternalSecretName, ExternalSecretNamespace).Write(&metric)).To(Succeed())
+				return metric.GetCounter().GetValue() >= 2.0
+			}, timeout, interval).Should(BeTrue())
+			Expect(externalSecretConditionShouldBe(ExternalSecretName, ExternalSecretNamespace, esv1beta1.ExternalSecretReady, v1.ConditionFalse, 1.0)).To(BeTrue())
+			Expect(externalSecretConditionShouldBe(ExternalSecretName, ExternalSecretNamespace, esv1beta1.ExternalSecretReady, v1.ConditionTrue, 0.0)).To(BeTrue())
+		}
+
+	}
+	// with rewrite keys from dataFrom
+	// should error if keys are not compliant
+	invalidFindKeysErrCondition := func(tc *testCase) {
+		tc.externalSecret.Spec.Data = nil
+		tc.externalSecret.Spec.DataFrom = []esv1beta1.ExternalSecretDataFromRemoteRef{
+			{
+				Find: &esv1beta1.ExternalSecretFind{
+					Name: &esv1beta1.FindName{
+						RegExp: ".*",
+					},
+				},
+				Rewrite: []esv1beta1.ExternalSecretRewrite{{
+					Regexp: &esv1beta1.ExternalSecretRewriteRegexp{
+						Source: "(.*)",
+						Target: "$1",
+					},
+				}},
+			},
+		}
+		fakeProvider.WithGetAllSecrets(map[string][]byte{
+			"foo/bar": []byte(FooValue),
+			"bar/foo": []byte(BarValue),
+		}, nil)
+		tc.checkCondition = func(es *esv1beta1.ExternalSecret) bool {
+			cond := GetExternalSecretCondition(es.Status, esv1beta1.ExternalSecretReady)
+			if cond == nil || cond.Status != v1.ConditionFalse || cond.Reason != esv1beta1.ConditionReasonSecretSyncedError {
+				return false
+			}
+			return true
+		}
+		tc.checkCondition = func(es *esv1beta1.ExternalSecret) bool {
+			cond := GetExternalSecretCondition(es.Status, esv1beta1.ExternalSecretReady)
+			if cond == nil || cond.Status != v1.ConditionFalse || cond.Reason != esv1beta1.ConditionReasonSecretSyncedError {
+				return false
+			}
+			return true
+		}
+		tc.checkExternalSecret = func(es *esv1beta1.ExternalSecret) {
+			Eventually(func() bool {
+				Expect(syncCallsError.WithLabelValues(ExternalSecretName, ExternalSecretNamespace).Write(&metric)).To(Succeed())
+				return metric.GetCounter().GetValue() >= 2.0
+			}, timeout, interval).Should(BeTrue())
+			Expect(externalSecretConditionShouldBe(ExternalSecretName, ExternalSecretNamespace, esv1beta1.ExternalSecretReady, v1.ConditionFalse, 1.0)).To(BeTrue())
+			Expect(externalSecretConditionShouldBe(ExternalSecretName, ExternalSecretNamespace, esv1beta1.ExternalSecretReady, v1.ConditionTrue, 0.0)).To(BeTrue())
+		}
+
+	}
+
 	// with dataFrom all properties from the specified secret
 	// with dataFrom all properties from the specified secret
 	// should be put into the secret
 	// should be put into the secret
 	syncWithDataFrom := func(tc *testCase) {
 	syncWithDataFrom := func(tc *testCase) {
@@ -966,6 +1099,37 @@ var _ = Describe("ExternalSecret controller", func() {
 			Expect(string(secret.Data["bar"])).To(Equal(BarValue))
 			Expect(string(secret.Data["bar"])).To(Equal(BarValue))
 		}
 		}
 	}
 	}
+	// with dataFrom.Find the change is on the called method GetAllSecrets
+	// all keys should be put into the secret
+	syncAndRewriteDataFromFind := func(tc *testCase) {
+		tc.externalSecret.Spec.Data = nil
+		tc.externalSecret.Spec.DataFrom = []esv1beta1.ExternalSecretDataFromRemoteRef{
+			{
+				Find: &esv1beta1.ExternalSecretFind{
+					Name: &esv1beta1.FindName{
+						RegExp: "foobar",
+					},
+				},
+				Rewrite: []esv1beta1.ExternalSecretRewrite{
+					{
+						Regexp: &esv1beta1.ExternalSecretRewriteRegexp{
+							Source: "(.*)",
+							Target: "new-$1",
+						},
+					},
+				},
+			},
+		}
+		fakeProvider.WithGetAllSecrets(map[string][]byte{
+			"foo": []byte(FooValue),
+			"bar": []byte(BarValue),
+		}, nil)
+		tc.checkSecret = func(es *esv1beta1.ExternalSecret, secret *v1.Secret) {
+			// check values
+			Expect(string(secret.Data["new-foo"])).To(Equal(FooValue))
+			Expect(string(secret.Data["new-bar"])).To(Equal(BarValue))
+		}
+	}
 
 
 	// with dataFrom.Find the change is on the called method GetAllSecrets
 	// with dataFrom.Find the change is on the called method GetAllSecrets
 	// all keys should be put into the secret
 	// all keys should be put into the secret
@@ -1284,7 +1448,11 @@ var _ = Describe("ExternalSecret controller", func() {
 		Entry("should refresh secret map when provider secret changes when using a template", refreshSecretValueMapTemplate),
 		Entry("should refresh secret map when provider secret changes when using a template", refreshSecretValueMapTemplate),
 		Entry("should not refresh secret value when provider secret changes but refreshInterval is zero", refreshintervalZero),
 		Entry("should not refresh secret value when provider secret changes but refreshInterval is zero", refreshintervalZero),
 		Entry("should fetch secret using dataFrom", syncWithDataFrom),
 		Entry("should fetch secret using dataFrom", syncWithDataFrom),
+		Entry("should rewrite secret using dataFrom", syncAndRewriteWithDataFrom),
+		Entry("should not automatically convert from extract if rewrite is used", invalidExtractKeysErrCondition),
 		Entry("should fetch secret using dataFrom.find", syncDataFromFind),
 		Entry("should fetch secret using dataFrom.find", syncDataFromFind),
+		Entry("should rewrite secret using dataFrom.find", syncAndRewriteDataFromFind),
+		Entry("should not automatically convert from find if rewrite is used", invalidFindKeysErrCondition),
 		Entry("should fetch secret using dataFrom and a template", syncWithDataFromTemplate),
 		Entry("should fetch secret using dataFrom and a template", syncWithDataFromTemplate),
 		Entry("should set error condition when provider errors", providerErrCondition),
 		Entry("should set error condition when provider errors", providerErrCondition),
 		Entry("should set an error condition when store does not exist", storeMissingErrCondition),
 		Entry("should set an error condition when store does not exist", storeMissingErrCondition),

+ 5 - 1
pkg/provider/akeyless/akeyless_api.go

@@ -132,8 +132,12 @@ func (a *akeylessBase) GetRotatedSecrets(secretName, token string, version int32
 		return "", fmt.Errorf("can't get rotated secret value: %w", err)
 		return "", fmt.Errorf("can't get rotated secret value: %w", err)
 	}
 	}
 
 
-	val, ok := gsvOut["value"]
+	valI, ok := gsvOut["value"]
 	if ok {
 	if ok {
+		val, convert := valI.(map[string]interface{})
+		if !convert {
+			return "", fmt.Errorf("failure converting key from gsvOut")
+		}
 		if _, ok := val["payload"]; ok {
 		if _, ok := val["payload"]; ok {
 			return fmt.Sprintf("%v", val["payload"]), nil
 			return fmt.Sprintf("%v", val["payload"]), nil
 		} else if _, ok := val["target_value"]; ok {
 		} else if _, ok := val["target_value"]; ok {

+ 68 - 19
pkg/provider/ibm/provider.go

@@ -17,6 +17,7 @@ import (
 	"context"
 	"context"
 	"encoding/json"
 	"encoding/json"
 	"fmt"
 	"fmt"
+	"os"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
 	"time"
 	"time"
@@ -555,16 +556,29 @@ func (ibm *providerIBM) ValidateStore(store esv1beta1.GenericStore) error {
 	if ibmSpec.ServiceURL == nil {
 	if ibmSpec.ServiceURL == nil {
 		return fmt.Errorf("serviceURL is required")
 		return fmt.Errorf("serviceURL is required")
 	}
 	}
-	secretRef := ibmSpec.Auth.SecretRef.SecretAPIKey
-	err := utils.ValidateSecretSelector(store, secretRef)
-	if err != nil {
-		return err
-	}
-	if secretRef.Name == "" {
-		return fmt.Errorf("secretAPIKey.name cannot be empty")
-	}
-	if secretRef.Key == "" {
-		return fmt.Errorf("secretAPIKey.key cannot be empty")
+
+	containerRef := ibmSpec.Auth.ContainerAuth
+	secretKeyRef := ibmSpec.Auth.SecretRef.SecretAPIKey
+	if utils.IsNil(containerRef.Profile) || (containerRef.Profile == "") {
+		// proceed with API Key Auth validation
+		err := utils.ValidateSecretSelector(store, secretKeyRef)
+		if err != nil {
+			return err
+		}
+		if secretKeyRef.Name == "" {
+			return fmt.Errorf("secretAPIKey.name cannot be empty")
+		}
+		if secretKeyRef.Key == "" {
+			return fmt.Errorf("secretAPIKey.key cannot be empty")
+		}
+	} else {
+		// proceed with container auth
+		if containerRef.TokenLocation == "" {
+			containerRef.TokenLocation = "/var/run/secrets/tokens/vault-token"
+		}
+		if _, err := os.Open(containerRef.TokenLocation); err != nil {
+			return fmt.Errorf("cannot read container auth token %s. %w", containerRef.TokenLocation, err)
+		}
 	}
 	}
 	return nil
 	return nil
 }
 }
@@ -585,16 +599,51 @@ func (ibm *providerIBM) NewClient(ctx context.Context, store esv1beta1.GenericSt
 		storeKind: store.GetObjectKind().GroupVersionKind().Kind,
 		storeKind: store.GetObjectKind().GroupVersionKind().Kind,
 	}
 	}
 
 
-	if err := iStore.setAuth(ctx); err != nil {
-		return nil, err
-	}
+	var err error
+	var secretsManager *sm.SecretsManagerV1
+	containerAuthProfile := iStore.store.Auth.ContainerAuth.Profile
+	if containerAuthProfile != "" {
+		// container-based auth
+		containerAuthToken := iStore.store.Auth.ContainerAuth.TokenLocation
+		containerAuthEndpoint := iStore.store.Auth.ContainerAuth.IAMEndpoint
+
+		if containerAuthToken == "" {
+			// API default path
+			containerAuthToken = "/var/run/secrets/tokens/vault-token"
+		}
+		if containerAuthEndpoint == "" {
+			// API default path
+			containerAuthEndpoint = "https://iam.cloud.ibm.com"
+		}
 
 
-	secretsManager, err := sm.NewSecretsManagerV1(&sm.SecretsManagerV1Options{
-		URL: *storeSpec.Provider.IBM.ServiceURL,
-		Authenticator: &core.IamAuthenticator{
-			ApiKey: string(iStore.credentials),
-		},
-	})
+		authenticator, err := core.NewContainerAuthenticatorBuilder().
+			SetIAMProfileName(containerAuthProfile).
+			SetCRTokenFilename(containerAuthToken).
+			SetURL(containerAuthEndpoint).
+			Build()
+		if err != nil {
+			return nil, fmt.Errorf(errIBMClient, err)
+		}
+		secretsManager, err = sm.NewSecretsManagerV1(&sm.SecretsManagerV1Options{
+			URL:           *storeSpec.Provider.IBM.ServiceURL,
+			Authenticator: authenticator,
+		})
+		if err != nil {
+			return nil, fmt.Errorf(errIBMClient, err)
+		}
+	} else {
+		// API Key-based auth
+		if err := iStore.setAuth(ctx); err != nil {
+			return nil, err
+		}
+
+		secretsManager, err = sm.NewSecretsManagerV1(&sm.SecretsManagerV1Options{
+			URL: *storeSpec.Provider.IBM.ServiceURL,
+			Authenticator: &core.IamAuthenticator{
+				ApiKey: string(iStore.credentials),
+			},
+		})
+	}
 
 
 	// Setup retry options, but only if present
 	// Setup retry options, but only if present
 	if storeSpec.RetrySettings != nil {
 	if storeSpec.RetrySettings != nil {

+ 13 - 0
pkg/provider/ibm/provider_test.go

@@ -134,6 +134,8 @@ func TestValidateStore(t *testing.T) {
 	}
 	}
 	url := "my-url"
 	url := "my-url"
 	store.Spec.Provider.IBM.ServiceURL = &url
 	store.Spec.Provider.IBM.ServiceURL = &url
+	var nilProfile esv1beta1.IBMAuthContainerAuth
+	store.Spec.Provider.IBM.Auth.ContainerAuth = nilProfile
 	err = p.ValidateStore(store)
 	err = p.ValidateStore(store)
 	if err == nil {
 	if err == nil {
 		t.Errorf(errExpectedErr)
 		t.Errorf(errExpectedErr)
@@ -150,6 +152,17 @@ func TestValidateStore(t *testing.T) {
 	} else if err.Error() != "namespace not allowed with namespaced SecretStore" {
 	} else if err.Error() != "namespace not allowed with namespaced SecretStore" {
 		t.Errorf("KeySelector test failed: expected namespace not allowed, got %v", err)
 		t.Errorf("KeySelector test failed: expected namespace not allowed, got %v", err)
 	}
 	}
+
+	// add container auth test
+	store.Spec.Provider.IBM = &esv1beta1.IBMProvider{}
+	store.Spec.Provider.IBM.ServiceURL = &url
+	store.Spec.Provider.IBM.Auth.ContainerAuth.Profile = "Trusted IAM Profile"
+	store.Spec.Provider.IBM.Auth.ContainerAuth.TokenLocation = "/a/path/to/nowhere/that/should/exist"
+	err = p.ValidateStore(store)
+	expected := "cannot read container auth token"
+	if !ErrorContains(err, expected) {
+		t.Errorf("ProfileSelector test failed: %s, expected: '%s'", err.Error(), expected)
+	}
 }
 }
 
 
 // test the sm<->gcp interface
 // test the sm<->gcp interface

+ 21 - 4
pkg/provider/onepassword/fake/fake.go

@@ -53,8 +53,11 @@ func (mockClient *OnePasswordMockClient) GetVaultByUUID(uuid string) (*onepasswo
 	return &onepassword.Vault{}, nil
 	return &onepassword.Vault{}, nil
 }
 }
 
 
-// GetVaultByTitle unused fake.
+// GetVaultByTitle returns a vault, you must preload, only one.
 func (mockClient *OnePasswordMockClient) GetVaultByTitle(uuid string) (*onepassword.Vault, error) {
 func (mockClient *OnePasswordMockClient) GetVaultByTitle(uuid string) (*onepassword.Vault, error) {
+	if len(mockClient.MockVaults[uuid]) != 0 {
+		return &mockClient.MockVaults[uuid][0], nil
+	}
 	return &onepassword.Vault{}, nil
 	return &onepassword.Vault{}, nil
 }
 }
 
 
@@ -82,9 +85,18 @@ func (mockClient *OnePasswordMockClient) GetItem(itemUUID, vaultUUID string) (*o
 	return &onepassword.Item{}, errors.New("status 400: Invalid Item UUID")
 	return &onepassword.Item{}, errors.New("status 400: Invalid Item UUID")
 }
 }
 
 
-// GetItemByUUID unused fake.
-func (mockClient *OnePasswordMockClient) GetItemByUUID(uuid, vaultQuery string) (*onepassword.Item, error) {
-	return &onepassword.Item{}, nil
+// GetItemByUUID returns a *onepassword.Item, you must preload.
+func (mockClient *OnePasswordMockClient) GetItemByUUID(itemUUID, vaultUUID string) (*onepassword.Item, error) {
+	for _, item := range mockClient.MockItems[vaultUUID] {
+		if item.ID == itemUUID {
+			// load the fields that GetItemsByTitle does not
+			item.Fields = mockClient.MockItemFields[vaultUUID][itemUUID]
+
+			return &item, nil
+		}
+	}
+
+	return &onepassword.Item{}, errors.New("status 400: Invalid Item UUID")
 }
 }
 
 
 // GetItemByTitle unused fake.
 // GetItemByTitle unused fake.
@@ -124,6 +136,11 @@ func (mockClient *OnePasswordMockClient) DeleteItemByID(itemUUID, vaultQuery str
 	return nil
 	return nil
 }
 }
 
 
+// DeleteItemByTitle unused fake.
+func (mockClient *OnePasswordMockClient) DeleteItemByTitle(title, vaultQuery string) error {
+	return nil
+}
+
 // GetFiles unused fake.
 // GetFiles unused fake.
 func (mockClient *OnePasswordMockClient) GetFiles(itemQuery, vaultQuery string) ([]onepassword.File, error) {
 func (mockClient *OnePasswordMockClient) GetFiles(itemQuery, vaultQuery string) ([]onepassword.File, error) {
 	return []onepassword.File{}, nil
 	return []onepassword.File{}, nil

+ 7 - 14
pkg/provider/onepassword/onepassword.go

@@ -45,7 +45,6 @@ const (
 	errFetchK8sSecret                             = "could not fetch ConnectToken Secret: %w"
 	errFetchK8sSecret                             = "could not fetch ConnectToken Secret: %w"
 	errMissingToken                               = "missing Secret Token"
 	errMissingToken                               = "missing Secret Token"
 	errGetVault                                   = "error finding 1Password Vault: %w"
 	errGetVault                                   = "error finding 1Password Vault: %w"
-	errExpectedOneVault                           = "expected one 1Password Vault matching %w"
 	errExpectedOneItem                            = "expected one 1Password Item matching %w"
 	errExpectedOneItem                            = "expected one 1Password Item matching %w"
 	errGetItem                                    = "error finding 1Password Item: %w"
 	errGetItem                                    = "error finding 1Password Item: %w"
 	errKeyNotFound                                = "key not found in 1Password Vaults: %w"
 	errKeyNotFound                                = "key not found in 1Password Vaults: %w"
@@ -183,7 +182,7 @@ func (provider *ProviderOnePassword) GetSecret(ctx context.Context, ref esv1beta
 // to be able to retrieve secrets from the provider.
 // to be able to retrieve secrets from the provider.
 func (provider *ProviderOnePassword) Validate() (esv1beta1.ValidationResult, error) {
 func (provider *ProviderOnePassword) Validate() (esv1beta1.ValidationResult, error) {
 	for vaultName := range provider.vaults {
 	for vaultName := range provider.vaults {
-		_, err := provider.client.GetItems(vaultName)
+		_, err := provider.client.GetVaultByTitle(vaultName)
 		if err != nil {
 		if err != nil {
 			return esv1beta1.ValidationResultError, err
 			return esv1beta1.ValidationResultError, err
 		}
 		}
@@ -221,15 +220,12 @@ func (provider *ProviderOnePassword) GetAllSecrets(ctx context.Context, ref esv1
 	secretData := make(map[string][]byte)
 	secretData := make(map[string][]byte)
 	sortedVaults := sortVaults(provider.vaults)
 	sortedVaults := sortVaults(provider.vaults)
 	for _, vaultName := range sortedVaults {
 	for _, vaultName := range sortedVaults {
-		vaults, err := provider.client.GetVaultsByTitle(vaultName)
+		vault, err := provider.client.GetVaultByTitle(vaultName)
 		if err != nil {
 		if err != nil {
 			return nil, fmt.Errorf(errGetVault, err)
 			return nil, fmt.Errorf(errGetVault, err)
 		}
 		}
-		if len(vaults) != 1 {
-			return nil, fmt.Errorf(errExpectedOneVault, fmt.Errorf(incorrectCountFormat, vaultName, len(vaults)))
-		}
 
 
-		err = provider.getAllForVault(vaults[0].ID, ref, secretData)
+		err = provider.getAllForVault(vault.ID, ref, secretData)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
@@ -246,22 +242,19 @@ func (provider *ProviderOnePassword) Close(ctx context.Context) error {
 func (provider *ProviderOnePassword) findItem(name string) (*onepassword.Item, error) {
 func (provider *ProviderOnePassword) findItem(name string) (*onepassword.Item, error) {
 	sortedVaults := sortVaults(provider.vaults)
 	sortedVaults := sortVaults(provider.vaults)
 	for _, vaultName := range sortedVaults {
 	for _, vaultName := range sortedVaults {
-		vaults, err := provider.client.GetVaultsByTitle(vaultName)
+		vault, err := provider.client.GetVaultByTitle(vaultName)
 		if err != nil {
 		if err != nil {
 			return nil, fmt.Errorf(errGetVault, err)
 			return nil, fmt.Errorf(errGetVault, err)
 		}
 		}
-		if len(vaults) != 1 {
-			return nil, fmt.Errorf(errExpectedOneVault, fmt.Errorf(incorrectCountFormat, vaultName, len(vaults)))
-		}
 
 
 		// use GetItemsByTitle instead of GetItemByTitle in order to handle length cases
 		// use GetItemsByTitle instead of GetItemByTitle in order to handle length cases
-		items, err := provider.client.GetItemsByTitle(name, vaults[0].ID)
+		items, err := provider.client.GetItemsByTitle(name, vault.ID)
 		if err != nil {
 		if err != nil {
 			return nil, fmt.Errorf(errGetItem, err)
 			return nil, fmt.Errorf(errGetItem, err)
 		}
 		}
 		switch {
 		switch {
 		case len(items) == 1:
 		case len(items) == 1:
-			return provider.client.GetItem(items[0].ID, items[0].Vault.ID)
+			return provider.client.GetItemByUUID(items[0].ID, items[0].Vault.ID)
 		case len(items) > 1:
 		case len(items) > 1:
 			return nil, fmt.Errorf(errExpectedOneItem, fmt.Errorf(incorrectCountFormat, name, len(items)))
 			return nil, fmt.Errorf(errExpectedOneItem, fmt.Errorf(incorrectCountFormat, name, len(items)))
 		}
 		}
@@ -311,7 +304,7 @@ func (provider *ProviderOnePassword) getFields(item *onepassword.Item, property
 }
 }
 
 
 func (provider *ProviderOnePassword) getAllFields(item onepassword.Item, ref esv1beta1.ExternalSecretFind, secretData map[string][]byte) error {
 func (provider *ProviderOnePassword) getAllFields(item onepassword.Item, ref esv1beta1.ExternalSecretFind, secretData map[string][]byte) error {
-	i, err := provider.client.GetItem(item.ID, item.Vault.ID)
+	i, err := provider.client.GetItemByUUID(item.ID, item.Vault.ID)
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf(errGetItem, err)
 		return fmt.Errorf(errGetItem, err)
 	}
 	}

+ 1 - 1
pkg/provider/onepassword/onepassword_test.go

@@ -172,7 +172,7 @@ func TestFindItem(t *testing.T) {
 				{
 				{
 					checkNote:    "two vaults",
 					checkNote:    "two vaults",
 					findItemName: myItem,
 					findItemName: myItem,
-					expectedErr:  fmt.Errorf(errExpectedOneVault, fmt.Errorf("'my-vault', got 2")),
+					expectedErr:  fmt.Errorf("key not found in 1Password Vaults: my-item in: map[my-shared-vault:2 my-vault:1]"),
 				},
 				},
 			},
 			},
 		},
 		},

+ 3 - 0
pkg/provider/vault/vault.go

@@ -485,6 +485,9 @@ func (v *client) listSecrets(ctx context.Context, path string) ([]string, error)
 		return nil, err
 		return nil, err
 	}
 	}
 	secret, err := v.logical.ListWithContext(ctx, url)
 	secret, err := v.logical.ListWithContext(ctx, url)
+	if secret == nil {
+		return nil, fmt.Errorf("provided path %v does not contain any secrets", url)
+	}
 	if err != nil {
 	if err != nil {
 		return nil, fmt.Errorf(errReadSecret, err)
 		return nil, fmt.Errorf(errReadSecret, err)
 	}
 	}

+ 49 - 0
pkg/utils/utils.go

@@ -24,6 +24,7 @@ import (
 	"net"
 	"net"
 	"net/url"
 	"net/url"
 	"reflect"
 	"reflect"
+	"regexp"
 	"strings"
 	"strings"
 	"time"
 	"time"
 	"unicode"
 	"unicode"
@@ -40,6 +41,34 @@ func MergeByteMap(dst, src map[string][]byte) map[string][]byte {
 	return dst
 	return dst
 }
 }
 
 
+func RewriteMap(operations []esv1beta1.ExternalSecretRewrite, in map[string][]byte) (map[string][]byte, error) {
+	out := in
+	var err error
+	for i, op := range operations {
+		if op.Regexp != nil {
+			out, err = RewriteRegexp(*op.Regexp, out)
+			if err != nil {
+				return nil, fmt.Errorf("failed rewriting operation[%v]: %w", i, err)
+			}
+		}
+	}
+	return out, nil
+}
+
+// RewriteRegexp rewrites a single Regexp Rewrite Operation.
+func RewriteRegexp(operation esv1beta1.ExternalSecretRewriteRegexp, in map[string][]byte) (map[string][]byte, error) {
+	out := make(map[string][]byte)
+	re, err := regexp.Compile(operation.Source)
+	if err != nil {
+		return nil, err
+	}
+	for key, value := range in {
+		newKey := re.ReplaceAllString(key, operation.Target)
+		out[newKey] = value
+	}
+	return out, nil
+}
+
 // DecodeValues decodes values from a secretMap.
 // DecodeValues decodes values from a secretMap.
 func DecodeMap(strategy esv1beta1.ExternalSecretDecodingStrategy, in map[string][]byte) (map[string][]byte, error) {
 func DecodeMap(strategy esv1beta1.ExternalSecretDecodingStrategy, in map[string][]byte) (map[string][]byte, error) {
 	out := make(map[string][]byte, len(in))
 	out := make(map[string][]byte, len(in))
@@ -69,6 +98,9 @@ func Decode(strategy esv1beta1.ExternalSecretDecodingStrategy, in []byte) ([]byt
 		return out, nil
 		return out, nil
 	case esv1beta1.ExternalSecretDecodeNone:
 	case esv1beta1.ExternalSecretDecodeNone:
 		return in, nil
 		return in, nil
+	// default when stored version is v1alpha1
+	case "":
+		return in, nil
 	case esv1beta1.ExternalSecretDecodeAuto:
 	case esv1beta1.ExternalSecretDecodeAuto:
 		out, err := Decode(esv1beta1.ExternalSecretDecodeBase64, in)
 		out, err := Decode(esv1beta1.ExternalSecretDecodeBase64, in)
 		if err != nil {
 		if err != nil {
@@ -84,6 +116,21 @@ func Decode(strategy esv1beta1.ExternalSecretDecodingStrategy, in []byte) ([]byt
 	}
 	}
 }
 }
 
 
+func ValidateKeys(in map[string][]byte) bool {
+	for key := range in {
+		for _, v := range key {
+			if !unicode.IsNumber(v) &&
+				!unicode.IsLetter(v) &&
+				v != '-' &&
+				v != '.' &&
+				v != '_' {
+				return false
+			}
+		}
+	}
+	return true
+}
+
 // ConvertKeys converts a secret map into a valid key.
 // ConvertKeys converts a secret map into a valid key.
 // Replaces any non-alphanumeric characters depending on convert strategy.
 // Replaces any non-alphanumeric characters depending on convert strategy.
 func ConvertKeys(strategy esv1beta1.ExternalSecretConversionStrategy, in map[string][]byte) (map[string][]byte, error) {
 func ConvertKeys(strategy esv1beta1.ExternalSecretConversionStrategy, in map[string][]byte) (map[string][]byte, error) {
@@ -112,6 +159,8 @@ func convert(strategy esv1beta1.ExternalSecretConversionStrategy, str string) st
 				newName[rk] = "_"
 				newName[rk] = "_"
 			case esv1beta1.ExternalSecretConversionUnicode:
 			case esv1beta1.ExternalSecretConversionUnicode:
 				newName[rk] = fmt.Sprintf("_U%04x_", rv)
 				newName[rk] = fmt.Sprintf("_U%04x_", rv)
+			default:
+				newName[rk] = string(rv)
 			}
 			}
 		} else {
 		} else {
 			newName[rk] = string(rv)
 			newName[rk] = string(rv)

+ 158 - 0
pkg/utils/utils_test.go

@@ -335,3 +335,161 @@ func TestValidate(t *testing.T) {
 		t.Errorf("Connection problem: %v", err)
 		t.Errorf("Connection problem: %v", err)
 	}
 	}
 }
 }
+
+func TestRewriteRegexp(t *testing.T) {
+	type args struct {
+		operations []esv1beta1.ExternalSecretRewrite
+		in         map[string][]byte
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    map[string][]byte
+		wantErr bool
+	}{
+		{
+			name: "replace of a single key",
+			args: args{
+				operations: []esv1beta1.ExternalSecretRewrite{
+					{
+						Regexp: &esv1beta1.ExternalSecretRewriteRegexp{
+							Source: "-",
+							Target: "_",
+						},
+					},
+				},
+				in: map[string][]byte{
+					"foo-bar": []byte("bar"),
+				},
+			},
+			want: map[string][]byte{
+				"foo_bar": []byte("bar"),
+			},
+		},
+		{
+			name: "no operation",
+			args: args{
+				operations: []esv1beta1.ExternalSecretRewrite{
+					{
+						Regexp: &esv1beta1.ExternalSecretRewriteRegexp{
+							Source: "hello",
+							Target: "world",
+						},
+					},
+				},
+				in: map[string][]byte{
+					"foo": []byte("bar"),
+				},
+			},
+			want: map[string][]byte{
+				"foo": []byte("bar"),
+			},
+		},
+		{
+			name: "removing prefix from keys",
+			args: args{
+				operations: []esv1beta1.ExternalSecretRewrite{
+					{
+						Regexp: &esv1beta1.ExternalSecretRewriteRegexp{
+							Source: "^my/initial/path/",
+							Target: "",
+						},
+					},
+				},
+				in: map[string][]byte{
+					"my/initial/path/foo": []byte("bar"),
+				},
+			},
+			want: map[string][]byte{
+				"foo": []byte("bar"),
+			},
+		},
+		{
+			name: "using un-named capture groups",
+			args: args{
+				operations: []esv1beta1.ExternalSecretRewrite{
+					{
+						Regexp: &esv1beta1.ExternalSecretRewriteRegexp{
+							Source: "f(.*)o",
+							Target: "a_new_path_$1",
+						},
+					},
+				},
+				in: map[string][]byte{
+					"foo":      []byte("bar"),
+					"foodaloo": []byte("barr"),
+				},
+			},
+			want: map[string][]byte{
+				"a_new_path_o":      []byte("bar"),
+				"a_new_path_oodalo": []byte("barr"),
+			},
+		},
+		{
+			name: "using named and numbered capture groups",
+			args: args{
+				operations: []esv1beta1.ExternalSecretRewrite{
+					{
+						Regexp: &esv1beta1.ExternalSecretRewriteRegexp{
+							Source: "f(?P<content>.*)o",
+							Target: "a_new_path_${content}_${1}",
+						},
+					},
+				},
+				in: map[string][]byte{
+					"foo":  []byte("bar"),
+					"floo": []byte("barr"),
+				},
+			},
+			want: map[string][]byte{
+				"a_new_path_o_o":   []byte("bar"),
+				"a_new_path_lo_lo": []byte("barr"),
+			},
+		},
+		{
+			name: "using sequenced rewrite operations",
+			args: args{
+				operations: []esv1beta1.ExternalSecretRewrite{
+					{
+						Regexp: &esv1beta1.ExternalSecretRewriteRegexp{
+							Source: "my/(.*?)/bar/(.*)",
+							Target: "$1-$2",
+						},
+					},
+					{
+						Regexp: &esv1beta1.ExternalSecretRewriteRegexp{
+							Source: "-",
+							Target: "_",
+						},
+					},
+					{
+						Regexp: &esv1beta1.ExternalSecretRewriteRegexp{
+							Source: "ass",
+							Target: "***",
+						},
+					},
+				},
+				in: map[string][]byte{
+					"my/app/bar/key":      []byte("bar"),
+					"my/app/bar/password": []byte("barr"),
+				},
+			},
+			want: map[string][]byte{
+				"app_key":      []byte("bar"),
+				"app_p***word": []byte("barr"),
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := RewriteMap(tt.args.operations, tt.args.in)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("RewriteMap() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("RewriteMap() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}