Преглед изворни кода

Add support for Yandex Lockbox

zamysel пре 4 година
родитељ
комит
7017935888

+ 4 - 0
apis/externalsecrets/v1alpha1/secretstore_types.go

@@ -53,6 +53,10 @@ type SecretStoreProvider struct {
 	// IBM configures this store to sync secrets using IBM Cloud provider
 	// IBM configures this store to sync secrets using IBM Cloud provider
 	// +optional
 	// +optional
 	IBM *IBMProvider `json:"ibm,omitempty"`
 	IBM *IBMProvider `json:"ibm,omitempty"`
+
+	// YandexLockbox configures this store to sync secrets using Yandex Lockbox provider
+	// +optional
+	YandexLockbox *YandexLockboxProvider `json:"yandexlockbox,omitempty"`
 }
 }
 
 
 type SecretStoreConditionType string
 type SecretStoreConditionType string

+ 31 - 0
apis/externalsecrets/v1alpha1/secretstore_yandexlockbox_types.go

@@ -0,0 +1,31 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1alpha1
+
+import (
+	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
+)
+
+type YandexLockboxAuth struct {
+	// The AuthorizedKey is used for authentication
+	// +optional
+	AuthorizedKey esmeta.SecretKeySelector `json:"authorizedKeySecretRef,omitempty"`
+}
+
+// YandexLockboxProvider Configures a store to sync secrets using the Yandex Lockbox provider.
+type YandexLockboxProvider struct {
+	// Auth defines the information necessary to authenticate against Yandex Lockbox
+	Auth YandexLockboxAuth `json:"auth"`
+}

+ 37 - 0
apis/externalsecrets/v1alpha1/zz_generated.deepcopy.go

@@ -644,6 +644,11 @@ func (in *SecretStoreProvider) DeepCopyInto(out *SecretStoreProvider) {
 		*out = new(IBMProvider)
 		*out = new(IBMProvider)
 		(*in).DeepCopyInto(*out)
 		(*in).DeepCopyInto(*out)
 	}
 	}
+	if in.YandexLockbox != nil {
+		in, out := &in.YandexLockbox, &out.YandexLockbox
+		*out = new(YandexLockboxProvider)
+		(*in).DeepCopyInto(*out)
+	}
 }
 }
 
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretStoreProvider.
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretStoreProvider.
@@ -949,3 +954,35 @@ func (in *VaultProvider) DeepCopy() *VaultProvider {
 	in.DeepCopyInto(out)
 	in.DeepCopyInto(out)
 	return out
 	return out
 }
 }
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *YandexLockboxAuth) DeepCopyInto(out *YandexLockboxAuth) {
+	*out = *in
+	in.AuthorizedKey.DeepCopyInto(&out.AuthorizedKey)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new YandexLockboxAuth.
+func (in *YandexLockboxAuth) DeepCopy() *YandexLockboxAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(YandexLockboxAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *YandexLockboxProvider) DeepCopyInto(out *YandexLockboxProvider) {
+	*out = *in
+	in.Auth.DeepCopyInto(&out.Auth)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new YandexLockboxProvider.
+func (in *YandexLockboxProvider) DeepCopy() *YandexLockboxProvider {
+	if in == nil {
+		return nil
+	}
+	out := new(YandexLockboxProvider)
+	in.DeepCopyInto(out)
+	return out
+}

+ 32 - 0
deploy/crds/external-secrets.io_clustersecretstores.yaml

@@ -608,6 +608,38 @@ spec:
                     - path
                     - path
                     - server
                     - server
                     type: object
                     type: object
+                  yandexlockbox:
+                    description: YandexLockbox configures this store to sync secrets
+                      using Yandex Lockbox provider
+                    properties:
+                      auth:
+                        description: Auth defines the information necessary to authenticate
+                          against Yandex Lockbox
+                        properties:
+                          authorizedKeySecretRef:
+                            description: The AuthorizedKey is used for authentication
+                            properties:
+                              key:
+                                description: The key of the entry in the Secret resource's
+                                  `data` field to be used. Some instances of this
+                                  field may be defaulted, in others it may be required.
+                                type: string
+                              name:
+                                description: The name of the Secret resource being
+                                  referred to.
+                                type: string
+                              namespace:
+                                description: Namespace of the resource being referred
+                                  to. Ignored if referent is not cluster-scoped. cluster-scoped
+                                  defaults to the namespace of the referent.
+                                type: string
+                            required:
+                            - name
+                            type: object
+                        type: object
+                    required:
+                    - auth
+                    type: object
                 type: object
                 type: object
             required:
             required:
             - provider
             - provider

+ 32 - 0
deploy/crds/external-secrets.io_secretstores.yaml

@@ -608,6 +608,38 @@ spec:
                     - path
                     - path
                     - server
                     - server
                     type: object
                     type: object
+                  yandexlockbox:
+                    description: YandexLockbox configures this store to sync secrets
+                      using Yandex Lockbox provider
+                    properties:
+                      auth:
+                        description: Auth defines the information necessary to authenticate
+                          against Yandex Lockbox
+                        properties:
+                          authorizedKeySecretRef:
+                            description: The AuthorizedKey is used for authentication
+                            properties:
+                              key:
+                                description: The key of the entry in the Secret resource's
+                                  `data` field to be used. Some instances of this
+                                  field may be defaulted, in others it may be required.
+                                type: string
+                              name:
+                                description: The name of the Secret resource being
+                                  referred to.
+                                type: string
+                              namespace:
+                                description: Namespace of the resource being referred
+                                  to. Ignored if referent is not cluster-scoped. cluster-scoped
+                                  defaults to the namespace of the referent.
+                                type: string
+                            required:
+                            - name
+                            type: object
+                        type: object
+                    required:
+                    - auth
+                    type: object
                 type: object
                 type: object
             required:
             required:
             - provider
             - provider

+ 2 - 0
go.mod

@@ -64,6 +64,8 @@ require (
 	github.com/spf13/cobra v1.1.3 // indirect
 	github.com/spf13/cobra v1.1.3 // indirect
 	github.com/stretchr/testify v1.7.0
 	github.com/stretchr/testify v1.7.0
 	github.com/tidwall/gjson v1.7.5
 	github.com/tidwall/gjson v1.7.5
+	github.com/yandex-cloud/go-genproto v0.0.0-20210809082946-a97da516c588
+	github.com/yandex-cloud/go-sdk v0.0.0-20210809100642-c13c40a429fa
 	github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a
 	github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a
 	go.uber.org/zap v1.17.0
 	go.uber.org/zap v1.17.0
 	golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83
 	golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83

+ 10 - 0
go.sum

@@ -98,6 +98,7 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ
 github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
 github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
 github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
 github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
+github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
 github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
@@ -135,6 +136,7 @@ github.com/decred/dcrd/chaincfg/chainhash v1.0.2/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D
 github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
 github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
 github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0 h1:sgNeV1VRMDzs6rzyPpxyM0jp317hnwiq58Filgag2xw=
 github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0 h1:sgNeV1VRMDzs6rzyPpxyM0jp317hnwiq58Filgag2xw=
 github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0/go.mod h1:J70FGZSbzsjecRTiTzER+3f1KZLNaXkuv+yeFTKoxM8=
 github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0/go.mod h1:J70FGZSbzsjecRTiTzER+3f1KZLNaXkuv+yeFTKoxM8=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
 github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
@@ -166,6 +168,7 @@ github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
 github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
@@ -479,6 +482,7 @@ github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
 github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
 github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
 github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
+github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
 github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
 github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
 github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
 github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
 github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
 github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
@@ -645,6 +649,10 @@ github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+
 github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
 github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+github.com/yandex-cloud/go-genproto v0.0.0-20210809082946-a97da516c588 h1:Lbz8X5Nre0Lg5QgCblmo0AhScWxeN3CVnX+mZ5Hxksk=
+github.com/yandex-cloud/go-genproto v0.0.0-20210809082946-a97da516c588/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE=
+github.com/yandex-cloud/go-sdk v0.0.0-20210809100642-c13c40a429fa h1:Un1jWl/YWbK1179aMbsEZ6uLlDjjBAjL8KXldho1Umo=
+github.com/yandex-cloud/go-sdk v0.0.0-20210809100642-c13c40a429fa/go.mod h1:UkgAKjyQo+Pylt2HTYz/G0PgnxmKOJ9IX/3XiRYQ9Ns=
 github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
 github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
 github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk=
 github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk=
 github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4=
 github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4=
@@ -763,6 +771,7 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
 golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
@@ -996,6 +1005,7 @@ google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfG
 google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200323114720-3f67cca34472/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=

+ 1 - 1
pkg/controllers/externalsecret/externalsecret_controller.go

@@ -147,7 +147,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
 	}
 	}
 
 
 	defer func() {
 	defer func() {
-		err = secretClient.Close()
+		err = secretClient.Close(ctx)
 		if err != nil {
 		if err != nil {
 			log.Error(err, errCloseStoreClient)
 			log.Error(err, errCloseStoreClient)
 		}
 		}

+ 1 - 1
pkg/provider/aws/parameterstore/parameterstore.go

@@ -90,6 +90,6 @@ func (pm *ParameterStore) GetSecretMap(ctx context.Context, ref esv1alpha1.Exter
 	return secretData, nil
 	return secretData, nil
 }
 }
 
 
-func (pm *ParameterStore) Close() error {
+func (pm *ParameterStore) Close(ctx context.Context) error {
 	return nil
 	return nil
 }
 }

+ 1 - 1
pkg/provider/aws/secretsmanager/secretsmanager.go

@@ -103,6 +103,6 @@ func (sm *SecretsManager) GetSecretMap(ctx context.Context, ref esv1alpha1.Exter
 	return secretData, nil
 	return secretData, nil
 }
 }
 
 
-func (sm *SecretsManager) Close() error {
+func (sm *SecretsManager) Close(ctx context.Context) error {
 	return nil
 	return nil
 }
 }

+ 1 - 1
pkg/provider/azure/keyvault/keyvault.go

@@ -227,7 +227,7 @@ func (a *Azure) secretKeyRef(ctx context.Context, namespace string, secretRef sm
 	return value, nil
 	return value, nil
 }
 }
 
 
-func (a *Azure) Close() error {
+func (a *Azure) Close(ctx context.Context) error {
 	return nil
 	return nil
 }
 }
 
 

+ 1 - 1
pkg/provider/fake/fake.go

@@ -74,7 +74,7 @@ func (v *Client) WithGetSecret(secData []byte, err error) *Client {
 func (v *Client) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
 func (v *Client) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
 	return v.GetSecretMapFn(ctx, ref)
 	return v.GetSecretMapFn(ctx, ref)
 }
 }
-func (v *Client) Close() error {
+func (v *Client) Close(ctx context.Context) error {
 	return nil
 	return nil
 }
 }
 
 

+ 1 - 1
pkg/provider/gcp/secretmanager/secretsmanager.go

@@ -199,7 +199,7 @@ func (sm *ProviderGCP) GetSecretMap(ctx context.Context, ref esv1alpha1.External
 	return secretData, nil
 	return secretData, nil
 }
 }
 
 
-func (sm *ProviderGCP) Close() error {
+func (sm *ProviderGCP) Close(ctx context.Context) error {
 	err := sm.SecretManagerClient.Close()
 	err := sm.SecretManagerClient.Close()
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf(errClientClose, err)
 		return fmt.Errorf(errClientClose, err)

+ 1 - 1
pkg/provider/ibm/provider.go

@@ -289,7 +289,7 @@ func (ibm *providerIBM) GetSecretMap(ctx context.Context, ref esv1alpha1.Externa
 	}
 	}
 }
 }
 
 
-func (ibm *providerIBM) Close() error {
+func (ibm *providerIBM) Close(ctx context.Context) error {
 	return nil
 	return nil
 }
 }
 
 

+ 1 - 1
pkg/provider/provider.go

@@ -35,5 +35,5 @@ type SecretsClient interface {
 
 
 	// GetSecretMap returns multiple k/v pairs from the provider
 	// GetSecretMap returns multiple k/v pairs from the provider
 	GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error)
 	GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error)
-	Close() error
+	Close(ctx context.Context) error
 }
 }

+ 1 - 0
pkg/provider/register/register.go

@@ -22,4 +22,5 @@ import (
 	_ "github.com/external-secrets/external-secrets/pkg/provider/gcp/secretmanager"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/gcp/secretmanager"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/ibm"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/ibm"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/vault"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/vault"
+	_ "github.com/external-secrets/external-secrets/pkg/provider/yandex/lockbox"
 )
 )

+ 1 - 1
pkg/provider/schema/schema_test.go

@@ -41,7 +41,7 @@ func (p *PP) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretData
 	return map[string][]byte{}, nil
 	return map[string][]byte{}, nil
 }
 }
 
 
-func (p *PP) Close() error {
+func (p *PP) Close(ctx context.Context) error {
 	return nil
 	return nil
 }
 }
 
 

+ 1 - 1
pkg/provider/vault/vault.go

@@ -155,7 +155,7 @@ func (v *client) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecret
 	return v.readSecret(ctx, ref.Key, ref.Version)
 	return v.readSecret(ctx, ref.Key, ref.Version)
 }
 }
 
 
-func (v *client) Close() error {
+func (v *client) Close(ctx context.Context) error {
 	return nil
 	return nil
 }
 }
 
 

+ 206 - 0
pkg/provider/yandex/lockbox/lockbox.go

@@ -0,0 +1,206 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package lockbox
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+
+	"github.com/yandex-cloud/go-genproto/yandex/cloud/lockbox/v1"
+	ycsdk "github.com/yandex-cloud/go-sdk"
+	"github.com/yandex-cloud/go-sdk/iamkey"
+	corev1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/types"
+	kclient "sigs.k8s.io/controller-runtime/pkg/client"
+
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	"github.com/external-secrets/external-secrets/pkg/provider"
+	"github.com/external-secrets/external-secrets/pkg/provider/schema"
+	"github.com/external-secrets/external-secrets/pkg/utils"
+)
+
+// providerLockbox is a provider for Yandex Lockbox.
+type providerLockbox struct {
+	sdk *ycsdk.SDK
+}
+
+// NewClient constructs a Yandex Lockbox Provider.
+func (p *providerLockbox) NewClient(ctx context.Context, store esv1alpha1.GenericStore, kube kclient.Client, namespace string) (provider.SecretsClient, error) {
+	storeSpec := store.GetSpec()
+	if storeSpec == nil || storeSpec.Provider == nil || storeSpec.Provider.YandexLockbox == nil {
+		return nil, fmt.Errorf("received invalid Yandex Lockbox SecretStore resource")
+	}
+	storeSpecYandexLockbox := storeSpec.Provider.YandexLockbox
+
+	authorizedKeySecretName := storeSpecYandexLockbox.Auth.AuthorizedKey.Name
+	if authorizedKeySecretName == "" {
+		return nil, fmt.Errorf("invalid Yandex Lockbox SecretStore resource: missing AuthorizedKey Name")
+	}
+	objectKey := types.NamespacedName{
+		Name:      authorizedKeySecretName,
+		Namespace: namespace,
+	}
+
+	// only ClusterStore is allowed to set namespace (and then it's required)
+	if store.GetObjectKind().GroupVersionKind().Kind == esv1alpha1.ClusterSecretStoreKind {
+		if storeSpecYandexLockbox.Auth.AuthorizedKey.Namespace == nil {
+			return nil, fmt.Errorf("invalid ClusterSecretStore: missing AuthorizedKey Namespace")
+		}
+		objectKey.Namespace = *storeSpecYandexLockbox.Auth.AuthorizedKey.Namespace
+	}
+
+	authorizedKeySecret := &corev1.Secret{}
+	err := kube.Get(ctx, objectKey, authorizedKeySecret)
+	if err != nil {
+		return nil, fmt.Errorf("could not fetch AuthorizedKey secret: %w", err)
+	}
+
+	authorizedKeySecretData := authorizedKeySecret.Data[storeSpecYandexLockbox.Auth.AuthorizedKey.Key]
+	if (authorizedKeySecretData == nil) || (len(authorizedKeySecretData) == 0) {
+		return nil, fmt.Errorf("missing AuthorizedKey")
+	}
+
+	var authorizedKey iamkey.Key
+	err = json.Unmarshal(authorizedKeySecretData, &authorizedKey)
+	if err != nil {
+		return nil, fmt.Errorf("unable to unmarshal authorized key: %w", err)
+	}
+
+	credentials, err := ycsdk.ServiceAccountKey(&authorizedKey)
+	if err != nil {
+		return nil, fmt.Errorf("failed to create credentials: %w", err)
+	}
+
+	sdk, err := ycsdk.Build(ctx, ycsdk.Config{
+		Credentials: credentials,
+	})
+	if err != nil {
+		return nil, fmt.Errorf("failed to create Yandex.Cloud SDK: %w", err)
+	}
+
+	p.sdk = sdk
+
+	return p, nil
+}
+
+// GetSecret returns a single secret from the provider.
+func (p *providerLockbox) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) ([]byte, error) {
+	entries, err := requestPayload(ctx, p.sdk, ref.Key, ref.Version)
+	if err != nil {
+		return nil, err
+	}
+
+	if ref.Property == "" {
+		keyToValue := make(map[string]interface{}, len(entries))
+		for _, entry := range entries {
+			value, err := getValueAsIs(entry)
+			if err != nil {
+				return nil, err
+			}
+			keyToValue[entry.Key] = value
+		}
+		out, err := json.Marshal(keyToValue)
+		if err != nil {
+			return nil, fmt.Errorf("failed to marshal secret: %w", err)
+		}
+		return out, nil
+	}
+
+	entry, err := findEntryByKey(entries, ref.Property)
+	if err != nil {
+		return nil, err
+	}
+	return getValueAsBinary(entry)
+}
+
+// GetSecret returns a single secret from the provider.
+func requestPayload(ctx context.Context, sdk *ycsdk.SDK, secretID, versionID string) ([]*lockbox.Payload_Entry, error) {
+	if utils.IsNil(sdk) {
+		return nil, fmt.Errorf("provider Yandex Lockbox is not initialized")
+	}
+
+	payload, err := sdk.LockboxPayload().Payload().Get(ctx, &lockbox.GetPayloadRequest{
+		SecretId:  secretID,
+		VersionId: versionID,
+	})
+	if err != nil {
+		return nil, fmt.Errorf("unable to get secret payload: %w", err)
+	}
+
+	return payload.Entries, nil
+}
+
+// GetSecretMap returns multiple k/v pairs from the provider.
+func (p *providerLockbox) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
+	entries, err := requestPayload(ctx, p.sdk, ref.Key, ref.Version)
+	if err != nil {
+		return nil, err
+	}
+
+	secretMap := make(map[string][]byte, len(entries))
+	for _, entry := range entries {
+		value, err := getValueAsBinary(entry)
+		if err != nil {
+			return nil, err
+		}
+		secretMap[entry.Key] = value
+	}
+	return secretMap, nil
+}
+
+func (p *providerLockbox) Close(ctx context.Context) error {
+	err := p.sdk.Shutdown(ctx)
+	if err != nil {
+		return fmt.Errorf("failed to shutdown Yandex.Cloud SDK: %w", err)
+	}
+	return nil
+}
+
+func getValueAsIs(entry *lockbox.Payload_Entry) (interface{}, error) {
+	switch entry.Value.(type) {
+	case *lockbox.Payload_Entry_TextValue:
+		return entry.GetTextValue(), nil
+	case *lockbox.Payload_Entry_BinaryValue:
+		return entry.GetBinaryValue(), nil
+	default:
+		return nil, fmt.Errorf("unsupported payload value type, key: %v", entry.Key)
+	}
+}
+
+func getValueAsBinary(entry *lockbox.Payload_Entry) ([]byte, error) {
+	switch entry.Value.(type) {
+	case *lockbox.Payload_Entry_TextValue:
+		return []byte(entry.GetTextValue()), nil
+	case *lockbox.Payload_Entry_BinaryValue:
+		return entry.GetBinaryValue(), nil
+	default:
+		return nil, fmt.Errorf("unsupported payload value type, key: %v", entry.Key)
+	}
+}
+
+func findEntryByKey(entries []*lockbox.Payload_Entry, key string) (*lockbox.Payload_Entry, error) {
+	for i := range entries {
+		if entries[i].Key == key {
+			return entries[i], nil
+		}
+	}
+	return nil, fmt.Errorf("payload entry with key '%s' not found", key)
+}
+
+func init() {
+	schema.Register(&providerLockbox{}, &esv1alpha1.SecretStoreProvider{
+		YandexLockbox: &esv1alpha1.YandexLockboxProvider{},
+	})
+}