github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/libpages/cert_store_backed_by_kvstore.go (about) 1 // Copyright 2020 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package libpages 6 7 import ( 8 "context" 9 "encoding/base64" 10 11 "github.com/keybase/client/go/kbfs/libkbfs" 12 "github.com/keybase/client/go/protocol/keybase1" 13 "github.com/pkg/errors" 14 "golang.org/x/crypto/acme/autocert" 15 ) 16 17 type keybaseServiceOwner interface { 18 KeybaseService() libkbfs.KeybaseService 19 } 20 21 // certStoreBackedByKVStore is a wrapper around the KVStore in Keybase. No 22 // caching is done here since acme/autocert has an in-memory cache already. 23 type certStoreBackedByKVStore struct { 24 serviceOwner keybaseServiceOwner 25 } 26 27 var _ autocert.Cache = (*certStoreBackedByKVStore)(nil) 28 29 func newCertStoreBackedByKVStore(serviceOwner keybaseServiceOwner) autocert.Cache { 30 return &certStoreBackedByKVStore{ 31 serviceOwner: serviceOwner, 32 } 33 } 34 35 func encodeData(data []byte) string { 36 return base64.URLEncoding.EncodeToString(data) 37 } 38 39 func decodeData(str string) ([]byte, error) { 40 return base64.URLEncoding.DecodeString(str) 41 } 42 43 const certKVStoreNamespace = "cert-store-v1" 44 45 // Get implements the autocert.Cache interface. 46 func (s *certStoreBackedByKVStore) Get(ctx context.Context, key string) ([]byte, error) { 47 res, err := s.serviceOwner.KeybaseService().GetKVStoreClient().GetKVEntry(ctx, 48 keybase1.GetKVEntryArg{ 49 Namespace: certKVStoreNamespace, 50 EntryKey: key, 51 }) 52 if err != nil { 53 return nil, errors.WithMessage(err, "kvstore get error") 54 } 55 if res.EntryValue == nil { 56 return nil, errors.New("kvstore get error: empty result") 57 } 58 data, err := decodeData(*res.EntryValue) 59 if err != nil { 60 return nil, errors.WithMessage(err, "decodeData error") 61 } 62 return data, nil 63 } 64 65 // Put implements the autocert.Cache interface. 66 func (s *certStoreBackedByKVStore) Put(ctx context.Context, key string, data []byte) error { 67 _, err := s.serviceOwner.KeybaseService().GetKVStoreClient().PutKVEntry(ctx, 68 keybase1.PutKVEntryArg{ 69 Namespace: certKVStoreNamespace, 70 EntryKey: key, 71 EntryValue: encodeData(data), 72 }) 73 if err != nil { 74 return errors.WithMessage(err, "kvstore put error") 75 } 76 return nil 77 } 78 79 // Delete implements the autocert.Cache interface. 80 func (s *certStoreBackedByKVStore) Delete(ctx context.Context, key string) error { 81 _, err := s.serviceOwner.KeybaseService().GetKVStoreClient().DelKVEntry(ctx, keybase1.DelKVEntryArg{ 82 Namespace: certKVStoreNamespace, 83 EntryKey: key, 84 }) 85 if err != nil { 86 return errors.WithMessage(err, "kvstore del error") 87 } 88 return nil 89 }