2023-03-15 16:00:52 +00:00
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
2018-01-18 21:49:20 +00:00
package plugin
import (
"context"
"errors"
"google.golang.org/grpc"
2019-04-12 21:54:35 +00:00
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/sdk/plugin/pb"
2018-01-18 21:49:20 +00:00
)
2022-12-02 18:12:05 +00:00
var errMissingStorage = errors . New ( "missing storage implementation: this method should not be called during plugin Setup, but only during and after Initialize" )
2018-01-18 21:49:20 +00:00
func newGRPCStorageClient ( conn * grpc . ClientConn ) * GRPCStorageClient {
return & GRPCStorageClient {
client : pb . NewStorageClient ( conn ) ,
}
}
// GRPCStorageClient is an implementation of logical.Storage that communicates
// over RPC.
type GRPCStorageClient struct {
client pb . StorageClient
}
2018-01-19 06:44:44 +00:00
func ( s * GRPCStorageClient ) List ( ctx context . Context , prefix string ) ( [ ] string , error ) {
reply , err := s . client . List ( ctx , & pb . StorageListArgs {
2018-01-18 21:49:20 +00:00
Prefix : prefix ,
2018-02-06 18:52:35 +00:00
} , largeMsgGRPCCallOpts ... )
2018-01-18 21:49:20 +00:00
if err != nil {
2018-04-03 12:00:04 +00:00
return [ ] string { } , err
2018-01-18 21:49:20 +00:00
}
if reply . Err != "" {
return reply . Keys , errors . New ( reply . Err )
}
return reply . Keys , nil
}
2018-01-19 06:44:44 +00:00
func ( s * GRPCStorageClient ) Get ( ctx context . Context , key string ) ( * logical . StorageEntry , error ) {
reply , err := s . client . Get ( ctx , & pb . StorageGetArgs {
2018-01-18 21:49:20 +00:00
Key : key ,
2018-02-06 18:52:35 +00:00
} , largeMsgGRPCCallOpts ... )
2018-01-18 21:49:20 +00:00
if err != nil {
return nil , err
}
if reply . Err != "" {
return nil , errors . New ( reply . Err )
}
return pb . ProtoStorageEntryToLogicalStorageEntry ( reply . Entry ) , nil
}
2018-01-19 06:44:44 +00:00
func ( s * GRPCStorageClient ) Put ( ctx context . Context , entry * logical . StorageEntry ) error {
reply , err := s . client . Put ( ctx , & pb . StoragePutArgs {
2018-01-18 21:49:20 +00:00
Entry : pb . LogicalStorageEntryToProtoStorageEntry ( entry ) ,
2018-02-06 18:52:35 +00:00
} , largeMsgGRPCCallOpts ... )
2018-01-18 21:49:20 +00:00
if err != nil {
return err
}
if reply . Err != "" {
return errors . New ( reply . Err )
}
return nil
}
2018-01-19 06:44:44 +00:00
func ( s * GRPCStorageClient ) Delete ( ctx context . Context , key string ) error {
reply , err := s . client . Delete ( ctx , & pb . StorageDeleteArgs {
2018-01-18 21:49:20 +00:00
Key : key ,
} )
if err != nil {
return err
}
if reply . Err != "" {
return errors . New ( reply . Err )
}
return nil
}
2022-12-02 18:12:05 +00:00
// GRPCStorageServer is a net/rpc compatible structure for serving
2018-01-18 21:49:20 +00:00
type GRPCStorageServer struct {
2021-09-30 01:25:15 +00:00
pb . UnimplementedStorageServer
2018-01-18 21:49:20 +00:00
impl logical . Storage
}
func ( s * GRPCStorageServer ) List ( ctx context . Context , args * pb . StorageListArgs ) ( * pb . StorageListReply , error ) {
2022-12-02 18:12:05 +00:00
if s . impl == nil {
return nil , errMissingStorage
}
2018-01-19 06:44:44 +00:00
keys , err := s . impl . List ( ctx , args . Prefix )
2018-01-18 21:49:20 +00:00
return & pb . StorageListReply {
Keys : keys ,
Err : pb . ErrToString ( err ) ,
} , nil
}
func ( s * GRPCStorageServer ) Get ( ctx context . Context , args * pb . StorageGetArgs ) ( * pb . StorageGetReply , error ) {
2022-12-02 18:12:05 +00:00
if s . impl == nil {
return nil , errMissingStorage
}
2018-01-19 06:44:44 +00:00
storageEntry , err := s . impl . Get ( ctx , args . Key )
2022-03-15 20:17:55 +00:00
if storageEntry == nil {
return & pb . StorageGetReply {
Entry : nil ,
Err : pb . ErrToString ( err ) ,
} , nil
}
2018-01-18 21:49:20 +00:00
return & pb . StorageGetReply {
Entry : pb . LogicalStorageEntryToProtoStorageEntry ( storageEntry ) ,
Err : pb . ErrToString ( err ) ,
} , nil
}
func ( s * GRPCStorageServer ) Put ( ctx context . Context , args * pb . StoragePutArgs ) ( * pb . StoragePutReply , error ) {
2022-12-02 18:12:05 +00:00
if s . impl == nil {
return nil , errMissingStorage
}
2018-01-19 06:44:44 +00:00
err := s . impl . Put ( ctx , pb . ProtoStorageEntryToLogicalStorageEntry ( args . Entry ) )
2018-01-18 21:49:20 +00:00
return & pb . StoragePutReply {
Err : pb . ErrToString ( err ) ,
} , nil
}
func ( s * GRPCStorageServer ) Delete ( ctx context . Context , args * pb . StorageDeleteArgs ) ( * pb . StorageDeleteReply , error ) {
2022-12-02 18:12:05 +00:00
if s . impl == nil {
return nil , errMissingStorage
}
2018-01-19 06:44:44 +00:00
err := s . impl . Delete ( ctx , args . Key )
2018-01-18 21:49:20 +00:00
return & pb . StorageDeleteReply {
Err : pb . ErrToString ( err ) ,
} , nil
}
2019-02-12 17:31:03 +00:00
// NOOPStorage is used to deny access to the storage interface while running a
// backend plugin in metadata mode.
type NOOPStorage struct { }
func ( s * NOOPStorage ) List ( _ context . Context , prefix string ) ( [ ] string , error ) {
return [ ] string { } , nil
}
func ( s * NOOPStorage ) Get ( _ context . Context , key string ) ( * logical . StorageEntry , error ) {
return nil , nil
}
func ( s * NOOPStorage ) Put ( _ context . Context , entry * logical . StorageEntry ) error {
return nil
}
func ( s * NOOPStorage ) Delete ( _ context . Context , key string ) error {
return nil
}