github.com/hashicorp/vault/sdk@v0.13.0/plugin/serve.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package plugin
     5  
     6  import (
     7  	"crypto/tls"
     8  	"math"
     9  	"os"
    10  
    11  	log "github.com/hashicorp/go-hclog"
    12  	plugin "github.com/hashicorp/go-plugin"
    13  	"github.com/hashicorp/vault/sdk/helper/pluginutil"
    14  	"github.com/hashicorp/vault/sdk/logical"
    15  	"google.golang.org/grpc"
    16  )
    17  
    18  // BackendPluginName is the name of the plugin that can be
    19  // dispensed from the plugin server.
    20  const BackendPluginName = "backend"
    21  
    22  type TLSProviderFunc func() (*tls.Config, error)
    23  
    24  type ServeOpts struct {
    25  	BackendFactoryFunc logical.Factory
    26  	TLSProviderFunc    TLSProviderFunc
    27  	Logger             log.Logger
    28  }
    29  
    30  // Serve is a helper function used to serve a backend plugin. This
    31  // should be ran on the plugin's main process.
    32  func Serve(opts *ServeOpts) error {
    33  	logger := opts.Logger
    34  	if logger == nil {
    35  		logger = log.New(&log.LoggerOptions{
    36  			Level:      log.Trace,
    37  			Output:     os.Stderr,
    38  			JSONFormat: true,
    39  		})
    40  	}
    41  
    42  	// pluginMap is the map of plugins we can dispense.
    43  	pluginSets := map[int]plugin.PluginSet{
    44  		// Version 3 used to supports both protocols. We want to keep it around
    45  		// since it's possible old plugins built against this version will still
    46  		// work with gRPC. There is currently no difference between version 3
    47  		// and version 4.
    48  		3: {
    49  			"backend": &GRPCBackendPlugin{
    50  				Factory: opts.BackendFactoryFunc,
    51  				Logger:  logger,
    52  			},
    53  		},
    54  		4: {
    55  			"backend": &GRPCBackendPlugin{
    56  				Factory: opts.BackendFactoryFunc,
    57  				Logger:  logger,
    58  			},
    59  		},
    60  		5: {
    61  			"backend": &GRPCBackendPlugin{
    62  				Factory:             opts.BackendFactoryFunc,
    63  				MultiplexingSupport: false,
    64  				Logger:              logger,
    65  			},
    66  		},
    67  	}
    68  
    69  	err := pluginutil.OptionallyEnableMlock()
    70  	if err != nil {
    71  		return err
    72  	}
    73  
    74  	serveOpts := &plugin.ServeConfig{
    75  		HandshakeConfig:  HandshakeConfig,
    76  		VersionedPlugins: pluginSets,
    77  		TLSProvider:      opts.TLSProviderFunc,
    78  		Logger:           logger,
    79  
    80  		// A non-nil value here enables gRPC serving for this plugin...
    81  		GRPCServer: func(opts []grpc.ServerOption) *grpc.Server {
    82  			opts = append(opts, grpc.MaxRecvMsgSize(math.MaxInt32))
    83  			opts = append(opts, grpc.MaxSendMsgSize(math.MaxInt32))
    84  			return plugin.DefaultGRPCServer(opts)
    85  		},
    86  	}
    87  
    88  	plugin.Serve(serveOpts)
    89  
    90  	return nil
    91  }
    92  
    93  // ServeMultiplex is a helper function used to serve a backend plugin. This
    94  // should be ran on the plugin's main process.
    95  func ServeMultiplex(opts *ServeOpts) error {
    96  	logger := opts.Logger
    97  	if logger == nil {
    98  		logger = log.New(&log.LoggerOptions{
    99  			Level:      log.Trace,
   100  			Output:     os.Stderr,
   101  			JSONFormat: true,
   102  		})
   103  	}
   104  
   105  	// pluginMap is the map of plugins we can dispense.
   106  	pluginSets := map[int]plugin.PluginSet{
   107  		// Version 3 used to supports both protocols. We want to keep it around
   108  		// since it's possible old plugins built against this version will still
   109  		// work with gRPC. There is currently no difference between version 3
   110  		// and version 4.
   111  		3: {
   112  			"backend": &GRPCBackendPlugin{
   113  				Factory: opts.BackendFactoryFunc,
   114  				Logger:  logger,
   115  			},
   116  		},
   117  		4: {
   118  			"backend": &GRPCBackendPlugin{
   119  				Factory: opts.BackendFactoryFunc,
   120  				Logger:  logger,
   121  			},
   122  		},
   123  		5: {
   124  			"backend": &GRPCBackendPlugin{
   125  				Factory:             opts.BackendFactoryFunc,
   126  				MultiplexingSupport: true,
   127  				Logger:              logger,
   128  			},
   129  		},
   130  	}
   131  
   132  	err := pluginutil.OptionallyEnableMlock()
   133  	if err != nil {
   134  		return err
   135  	}
   136  
   137  	serveOpts := &plugin.ServeConfig{
   138  		HandshakeConfig:  HandshakeConfig,
   139  		VersionedPlugins: pluginSets,
   140  		Logger:           logger,
   141  
   142  		// A non-nil value here enables gRPC serving for this plugin...
   143  		GRPCServer: func(opts []grpc.ServerOption) *grpc.Server {
   144  			opts = append(opts, grpc.MaxRecvMsgSize(math.MaxInt32))
   145  			opts = append(opts, grpc.MaxSendMsgSize(math.MaxInt32))
   146  			return plugin.DefaultGRPCServer(opts)
   147  		},
   148  
   149  		// TLSProvider is required to support v3 and v4 plugins.
   150  		// It will be ignored for v5 which uses AutoMTLS
   151  		TLSProvider: opts.TLSProviderFunc,
   152  	}
   153  
   154  	plugin.Serve(serveOpts)
   155  
   156  	return nil
   157  }
   158  
   159  // handshakeConfigs are used to just do a basic handshake between
   160  // a plugin and host. If the handshake fails, a user friendly error is shown.
   161  // This prevents users from executing bad plugins or executing a plugin
   162  // directory. It is a UX feature, not a security feature.
   163  var HandshakeConfig = plugin.HandshakeConfig{
   164  	MagicCookieKey:   "VAULT_BACKEND_PLUGIN",
   165  	MagicCookieValue: "6669da05-b1c8-4f49-97d9-c8e5bed98e20",
   166  }