github.com/zntrio/harp/v2@v2.0.9/pkg/vault/kv/v1_service.go (about) 1 // Licensed to Elasticsearch B.V. under one or more contributor 2 // license agreements. See the NOTICE file distributed with 3 // this work for additional information regarding copyright 4 // ownership. Elasticsearch B.V. licenses this file to you under 5 // the Apache License, Version 2.0 (the "License"); you may 6 // not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, 12 // software distributed under the License is distributed on an 13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 // KIND, either express or implied. See the License for the 15 // specific language governing permissions and limitations 16 // under the License. 17 18 package kv 19 20 import ( 21 "context" 22 "fmt" 23 24 "github.com/zntrio/harp/v2/pkg/vault/logical" 25 vpath "github.com/zntrio/harp/v2/pkg/vault/path" 26 ) 27 28 type kvv1Backend struct { 29 logical logical.Logical 30 mountPath string 31 } 32 33 // V1 returns a K/V v1 backend service instance. 34 func V1(l logical.Logical, mountPath string) Service { 35 return &kvv1Backend{ 36 logical: l, 37 mountPath: mountPath, 38 } 39 } 40 41 // -----------------------------------------------------------------------------. 42 func (s *kvv1Backend) List(ctx context.Context, path string) ([]string, error) { 43 // Clean path first 44 secretPath := vpath.SanitizePath(path) 45 if secretPath == "" { 46 return nil, fmt.Errorf("unable to query with empty path") 47 } 48 49 // Create logical client 50 secret, err := s.logical.List(secretPath) 51 if err != nil { 52 return nil, fmt.Errorf("unable to list secret keys: %w", err) 53 } 54 if secret == nil { 55 // Path is a leaf 56 return nil, nil 57 } 58 if secret.Data == nil { 59 return nil, fmt.Errorf("invalid secret response") 60 } 61 62 // Check required property 63 k, ok := secret.Data["keys"] 64 if !ok || k == nil { 65 return nil, fmt.Errorf("invalid response missing 'keys' property") 66 } 67 68 // Check value type 69 r, ok := k.([]interface{}) 70 if !ok { 71 return nil, fmt.Errorf("invalid response 'keys' is not a list (%T)", k) 72 } 73 74 // Convert list of interface to list of string 75 out := make([]string, len(r)) 76 for i := range r { 77 out[i] = fmt.Sprintf("%v", r[i]) 78 } 79 80 // No error 81 return out, nil 82 } 83 84 func (s *kvv1Backend) Read(ctx context.Context, path string) (SecretData, SecretMetadata, error) { 85 // Clean path first 86 secretPath := vpath.SanitizePath(path) 87 if secretPath == "" { 88 return nil, nil, fmt.Errorf("unable to query with empty path") 89 } 90 91 // Create a logical client 92 secret, err := s.logical.Read(secretPath) 93 if err != nil { 94 return nil, nil, fmt.Errorf("unable to retrieve secret for path %q: %w", path, err) 95 } 96 if secret == nil { 97 return nil, nil, fmt.Errorf("unable to retrieve secret for path %q: %w", path, ErrPathNotFound) 98 } 99 if secret.Data == nil { 100 return nil, nil, fmt.Errorf("unable to retrieve secret for path %q: %w", path, ErrNoData) 101 } 102 103 // Return secret value and no error 104 return secret.Data, nil, err 105 } 106 107 func (s *kvv1Backend) ReadVersion(ctx context.Context, path string, version uint32) (SecretData, SecretMetadata, error) { 108 return s.Read(ctx, path) 109 } 110 111 func (s *kvv1Backend) Write(ctx context.Context, path string, data SecretData) error { 112 return s.WriteWithMeta(ctx, path, data, nil) 113 } 114 115 func (s *kvv1Backend) WriteWithMeta(ctx context.Context, path string, data SecretData, meta SecretMetadata) error { 116 // Clean path first 117 secretPath := vpath.SanitizePath(path) 118 if secretPath == "" { 119 return fmt.Errorf("unable to query with empty path") 120 } 121 122 // Add metadata as secret data. 123 if len(meta) > 0 { 124 data[VaultMetadataDataKey] = meta 125 } 126 127 // Create a logical client 128 _, err := s.logical.Write(secretPath, data) 129 if err != nil { 130 return fmt.Errorf("unable to write secret data for path %q: %w", path, err) 131 } 132 133 return nil 134 }