| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- /*
- Copyright © The ESO Authors
- 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
- https://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 ovh
- import (
- "context"
- "encoding/json"
- "errors"
- "fmt"
- "strconv"
- "github.com/google/uuid"
- "github.com/ovh/okms-sdk-go"
- "github.com/tidwall/gjson"
- esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
- )
- func (cl *ovhClient) getSecretWithOvhSDK(ctx context.Context, okmsID uuid.UUID, ref esv1.ExternalSecretDataRemoteRef) ([]byte, *uint32, error) {
- // Check if the remoteRef key is empty.
- if ref.Key == "" {
- return []byte{}, nil, errors.New("remote key cannot be empty (spec.data.remoteRef.key)")
- }
- // Check MetaDataPolicy (not supported).
- if ref.MetadataPolicy == esv1.ExternalSecretMetadataPolicyFetch {
- return []byte{}, nil, errors.New("fetch metadata policy not supported")
- }
- // Decode the secret version.
- versionAddr, err := decodeSecretVersion(ref.Version)
- if err != nil {
- return []byte{}, nil, err
- }
- // Retrieve the KMS secret.
- includeData := true
- secret, err := cl.okmsClient.GetSecretV2(ctx, okmsID, ref.Key, versionAddr, &includeData)
- if err != nil {
- return []byte{}, nil, handleOkmsError(err)
- }
- if secret == nil {
- return []byte{}, nil, esv1.NoSecretErr
- }
- if secret.Version == nil || secret.Version.Data == nil || len(*secret.Version.Data) == 0 {
- return []byte{}, nil, errors.New("secret version data is missing")
- }
- // Retrieve KMS Secret property if needed.
- var secretData []byte
- if ref.Property == "" {
- secretData, err = json.Marshal(secret.Version.Data)
- } else {
- secretData, err = getPropertyValue(*secret.Version.Data, ref.Property)
- }
- var currentVersion *uint32
- if secret.Metadata != nil {
- currentVersion = secret.Metadata.CurrentVersion
- }
- return secretData, currentVersion, err
- }
- // Decode a secret version.
- //
- // Returns nil if no version is provided; in that case, the OVH SDK uses the latest version.
- func decodeSecretVersion(strVersion string) (*uint32, error) {
- if strVersion == "" {
- return nil, nil
- }
- v, err := strconv.ParseUint(strVersion, 10, 32)
- if err != nil {
- return nil, fmt.Errorf("invalid secret version %q: %w", strVersion, err)
- }
- version := uint32(v)
- return &version, nil
- }
- // Retrieve the value of the secret property.
- func getPropertyValue(data map[string]any, property string) ([]byte, error) {
- // Marshal data into bytes so it can be passed to gjson.Get.
- secretData, err := json.Marshal(data)
- if err != nil {
- return []byte{}, err
- }
- // Retrieve the property value if it exists.
- secretDataResult := gjson.Get(string(secretData), property)
- if !secretDataResult.Exists() {
- return []byte{}, fmt.Errorf("secret property %q not found", property)
- }
- return []byte(secretDataResult.String()), nil
- }
- // Returns an okms.KmsError struct representing the KMS response
- // (error_code, error_id, errors, request_id).
- func handleOkmsError(err error) error {
- okmsError := okms.AsKmsError(err)
- if okmsError == nil {
- return fmt.Errorf("failed to parse the following okms error: %w", err)
- } else if okmsError.ErrorCode == 17125377 { // 17125377: returned by OKMS when secret was not found
- return esv1.NoSecretErr
- }
- return okmsError
- }
|