open-vault/builtin/logical/database/dbplugin/client.go

128 lines
3.1 KiB
Go
Raw Normal View History

2017-04-06 19:20:10 +00:00
package dbplugin
import (
"fmt"
"net/rpc"
"sync"
"time"
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/vault/helper/pluginutil"
)
// DatabasePluginClient embeds a databasePluginRPCClient and wraps it's close
// method to also call Kill() on the plugin.Client.
type DatabasePluginClient struct {
client *plugin.Client
sync.Mutex
*databasePluginRPCClient
}
func (dc *DatabasePluginClient) Close() error {
err := dc.databasePluginRPCClient.Close()
dc.client.Kill()
return err
}
// newPluginClient returns a databaseRPCClient with a connection to a running
// plugin. The client is wrapped in a DatabasePluginClient object to ensure the
// plugin is killed on call of Close().
func newPluginClient(sys pluginutil.Wrapper, pluginRunner *pluginutil.PluginRunner) (DatabaseType, error) {
// pluginMap is the map of plugins we can dispense.
var pluginMap = map[string]plugin.Plugin{
"database": new(DatabasePlugin),
}
client, err := pluginRunner.Run(sys, pluginMap, handshakeConfig, []string{})
if err != nil {
return nil, err
}
// Connect via RPC
rpcClient, err := client.Client()
if err != nil {
return nil, err
}
// Request the plugin
raw, err := rpcClient.Dispense("database")
if err != nil {
return nil, err
}
// We should have a Greeter now! This feels like a normal interface
// implementation but is in fact over an RPC connection.
databaseRPC := raw.(*databasePluginRPCClient)
return &DatabasePluginClient{
client: client,
databasePluginRPCClient: databaseRPC,
}, nil
}
// ---- RPC client domain ----
// databasePluginRPCClient impliments DatabaseType and is used on the client to
// make RPC calls to a plugin.
type databasePluginRPCClient struct {
client *rpc.Client
}
func (dr *databasePluginRPCClient) Type() string {
var dbType string
//TODO: catch error
dr.client.Call("Plugin.Type", struct{}{}, &dbType)
return fmt.Sprintf("plugin-%s", dbType)
}
func (dr *databasePluginRPCClient) CreateUser(statements Statements, usernamePrefix string, expiration time.Time) (username string, password string, err error) {
2017-04-06 19:20:10 +00:00
req := CreateUserRequest{
Statements: statements,
UsernamePrefix: usernamePrefix,
Expiration: expiration,
2017-04-06 19:20:10 +00:00
}
var resp CreateUserResponse
err = dr.client.Call("Plugin.CreateUser", req, &resp)
2017-04-06 19:20:10 +00:00
return resp.Username, resp.Password, err
2017-04-06 19:20:10 +00:00
}
func (dr *databasePluginRPCClient) RenewUser(statements Statements, username string, expiration time.Time) error {
2017-04-06 19:20:10 +00:00
req := RenewUserRequest{
Statements: statements,
Username: username,
Expiration: expiration,
}
err := dr.client.Call("Plugin.RenewUser", req, &struct{}{})
return err
}
func (dr *databasePluginRPCClient) RevokeUser(statements Statements, username string) error {
req := RevokeUserRequest{
Statements: statements,
Username: username,
}
err := dr.client.Call("Plugin.RevokeUser", req, &struct{}{})
return err
}
func (dr *databasePluginRPCClient) Initialize(conf map[string]interface{}) error {
err := dr.client.Call("Plugin.Initialize", conf, &struct{}{})
return err
}
func (dr *databasePluginRPCClient) Close() error {
err := dr.client.Call("Plugin.Close", struct{}{}, &struct{}{})
return err
}