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 }