1
0
Fork 0
mirror of https://github.com/external-secrets/external-secrets.git synced 2024-12-14 11:57:59 +00:00

Add support for Yandex Lockbox

This commit is contained in:
zamysel 2021-08-12 20:05:02 +03:00
parent 328cf881b8
commit 7017935888
19 changed files with 365 additions and 10 deletions

View file

@ -53,6 +53,10 @@ type SecretStoreProvider struct {
// IBM configures this store to sync secrets using IBM Cloud provider
// +optional
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

View file

@ -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"`
}

View file

@ -644,6 +644,11 @@ func (in *SecretStoreProvider) DeepCopyInto(out *SecretStoreProvider) {
*out = new(IBMProvider)
(*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.
@ -949,3 +954,35 @@ func (in *VaultProvider) DeepCopy() *VaultProvider {
in.DeepCopyInto(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
}

View file

@ -608,6 +608,38 @@ spec:
- path
- server
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
required:
- provider

View file

@ -608,6 +608,38 @@ spec:
- path
- server
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
required:
- provider

2
go.mod
View file

@ -64,6 +64,8 @@ require (
github.com/spf13/cobra v1.1.3 // indirect
github.com/stretchr/testify v1.7.0
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
go.uber.org/zap v1.17.0
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83

10
go.sum
View file

@ -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/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/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/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
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/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/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/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=
@ -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.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
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/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=
@ -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/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
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/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/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/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-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk=
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-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-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-20200501053045-e0ff5e5a1de5/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-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-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-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=

View file

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

View file

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

View file

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

View file

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

View file

@ -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) {
return v.GetSecretMapFn(ctx, ref)
}
func (v *Client) Close() error {
func (v *Client) Close(ctx context.Context) error {
return nil
}

View file

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

View file

@ -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
}

View file

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

View file

@ -22,4 +22,5 @@ import (
_ "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/vault"
_ "github.com/external-secrets/external-secrets/pkg/provider/yandex/lockbox"
)

View file

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

View file

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

View file

@ -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{},
})
}