diff --git a/audit/hashstructure.go b/audit/hashstructure.go index 8d0fd7c6c7..ea0899ee97 100644 --- a/audit/hashstructure.go +++ b/audit/hashstructure.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/hashicorp/vault/helper/salt" + "github.com/hashicorp/vault/helper/wrapping" "github.com/hashicorp/vault/logical" "github.com/mitchellh/copystructure" "github.com/mitchellh/reflectwalk" @@ -84,7 +85,7 @@ func Hash(salter *salt.Salt, raw interface{}) error { s.Data = data.(map[string]interface{}) - case *logical.ResponseWrapInfo: + case *wrapping.ResponseWrapInfo: if s == nil { return nil } diff --git a/audit/hashstructure_test.go b/audit/hashstructure_test.go index 5fefa0fa91..6916d0d3a3 100644 --- a/audit/hashstructure_test.go +++ b/audit/hashstructure_test.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/vault/helper/certutil" "github.com/hashicorp/vault/helper/salt" + "github.com/hashicorp/vault/helper/wrapping" "github.com/hashicorp/vault/logical" "github.com/mitchellh/copystructure" ) @@ -69,7 +70,7 @@ func TestCopy_response(t *testing.T) { Data: map[string]interface{}{ "foo": "bar", }, - WrapInfo: &logical.ResponseWrapInfo{ + WrapInfo: &wrapping.ResponseWrapInfo{ TTL: 60, Token: "foo", CreationTime: time.Now(), @@ -140,7 +141,7 @@ func TestHash(t *testing.T) { Data: map[string]interface{}{ "foo": "bar", }, - WrapInfo: &logical.ResponseWrapInfo{ + WrapInfo: &wrapping.ResponseWrapInfo{ TTL: 60, Token: "bar", CreationTime: now, @@ -151,7 +152,7 @@ func TestHash(t *testing.T) { Data: map[string]interface{}{ "foo": "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317", }, - WrapInfo: &logical.ResponseWrapInfo{ + WrapInfo: &wrapping.ResponseWrapInfo{ TTL: 60, Token: "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317", CreationTime: now, diff --git a/helper/pluginutil/mlock.go b/helper/pluginutil/mlock.go new file mode 100644 index 0000000000..dd9115a89a --- /dev/null +++ b/helper/pluginutil/mlock.go @@ -0,0 +1,23 @@ +package pluginutil + +import ( + "os" + + "github.com/hashicorp/vault/helper/mlock" +) + +var ( + // PluginUnwrapTokenEnv is the ENV name used to pass the configuration for + // enabling mlock + PluginMlockEnabled = "VAULT_PLUGIN_MLOCK_ENABLED" +) + +// OptionallyEnableMlock determines if mlock should be called, and if so enables +// mlock. +func OptionallyEnableMlock() error { + if os.Getenv(PluginMlockEnabled) == "true" { + return mlock.LockMemory() + } + + return nil +} diff --git a/helper/pluginutil/runner.go b/helper/pluginutil/runner.go index 9963704e54..539c3b4485 100644 --- a/helper/pluginutil/runner.go +++ b/helper/pluginutil/runner.go @@ -3,18 +3,11 @@ package pluginutil import ( "crypto/sha256" "fmt" - "os" "os/exec" "time" plugin "github.com/hashicorp/go-plugin" - "github.com/hashicorp/vault/helper/mlock" -) - -var ( - // PluginUnwrapTokenEnv is the ENV name used to pass the configuration for - // enabling mlock - PluginMlockEnabled = "VAULT_PLUGIN_MLOCK_ENABLED" + "github.com/hashicorp/vault/helper/wrapping" ) // Looker defines the plugin Lookup function that looks into the plugin catalog @@ -27,7 +20,7 @@ type Looker interface { // metadata needed to run a plugin process. This includes looking up Mlock // configuration and wrapping data in a respose wrapped token. type Wrapper interface { - ResponseWrapData(data map[string]interface{}, ttl time.Duration, jwt bool) (string, error) + ResponseWrapData(data map[string]interface{}, ttl time.Duration, jwt bool) (*wrapping.ResponseWrapInfo, error) MlockDisabled() bool } @@ -97,13 +90,3 @@ func (r *PluginRunner) Run(wrapper Wrapper, pluginMap map[string]plugin.Plugin, return client, nil } - -// OptionallyEnableMlock determines if mlock should be called, and if so enables -// mlock. -func OptionallyEnableMlock() error { - if os.Getenv(PluginMlockEnabled) == "true" { - return mlock.LockMemory() - } - - return nil -} diff --git a/helper/pluginutil/tls.go b/helper/pluginutil/tls.go index d4c0946e4f..ee0c54d89d 100644 --- a/helper/pluginutil/tls.go +++ b/helper/pluginutil/tls.go @@ -103,12 +103,15 @@ func WrapServerConfig(sys Wrapper, certBytes []byte, key *ecdsa.PrivateKey) (str return "", err } - wrapToken, err := sys.ResponseWrapData(map[string]interface{}{ + wrapInfo, err := sys.ResponseWrapData(map[string]interface{}{ "ServerCert": certBytes, "ServerKey": rawKey, }, time.Second*10, true) + if err != nil { + return "", err + } - return wrapToken, err + return wrapInfo.Token, nil } // VaultPluginTLSProvider is run inside a plugin and retrives the response diff --git a/helper/wrapping/wrapinfo.go b/helper/wrapping/wrapinfo.go new file mode 100644 index 0000000000..a27219b8a9 --- /dev/null +++ b/helper/wrapping/wrapinfo.go @@ -0,0 +1,23 @@ +package wrapping + +import "time" + +type ResponseWrapInfo struct { + // Setting to non-zero specifies that the response should be wrapped. + // Specifies the desired TTL of the wrapping token. + TTL time.Duration `json:"ttl" structs:"ttl" mapstructure:"ttl"` + + // The token containing the wrapped response + Token string `json:"token" structs:"token" mapstructure:"token"` + + // The creation time. This can be used with the TTL to figure out an + // expected expiration. + CreationTime time.Time `json:"creation_time" structs:"creation_time" mapstructure:"cration_time"` + + // If the contained response is the output of a token creation call, the + // created token's accessor will be accessible here + WrappedAccessor string `json:"wrapped_accessor" structs:"wrapped_accessor" mapstructure:"wrapped_accessor"` + + // The format to use. This doesn't get returned, it's only internal. + Format string `json:"format" structs:"format" mapstructure:"format"` +} diff --git a/logical/response.go b/logical/response.go index ee6bfe1e27..2a4646a2ca 100644 --- a/logical/response.go +++ b/logical/response.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" "reflect" - "time" + "github.com/hashicorp/vault/helper/wrapping" "github.com/mitchellh/copystructure" ) @@ -28,26 +28,6 @@ const ( HTTPStatusCode = "http_status_code" ) -type ResponseWrapInfo struct { - // Setting to non-zero specifies that the response should be wrapped. - // Specifies the desired TTL of the wrapping token. - TTL time.Duration `json:"ttl" structs:"ttl" mapstructure:"ttl"` - - // The token containing the wrapped response - Token string `json:"token" structs:"token" mapstructure:"token"` - - // The creation time. This can be used with the TTL to figure out an - // expected expiration. - CreationTime time.Time `json:"creation_time" structs:"creation_time" mapstructure:"cration_time"` - - // If the contained response is the output of a token creation call, the - // created token's accessor will be accessible here - WrappedAccessor string `json:"wrapped_accessor" structs:"wrapped_accessor" mapstructure:"wrapped_accessor"` - - // The format to use. This doesn't get returned, it's only internal. - Format string `json:"format" structs:"format" mapstructure:"format"` -} - // Response is a struct that stores the response of a request. // It is used to abstract the details of the higher level request protocol. type Response struct { @@ -78,7 +58,7 @@ type Response struct { warnings []string `json:"warnings" structs:"warnings" mapstructure:"warnings"` // Information for wrapping the response in a cubbyhole - WrapInfo *ResponseWrapInfo `json:"wrap_info" structs:"wrap_info" mapstructure:"wrap_info"` + WrapInfo *wrapping.ResponseWrapInfo `json:"wrap_info" structs:"wrap_info" mapstructure:"wrap_info"` } func init() { @@ -123,7 +103,7 @@ func init() { if err != nil { return nil, fmt.Errorf("error copying WrapInfo: %v", err) } - ret.WrapInfo = retWrapInfo.(*ResponseWrapInfo) + ret.WrapInfo = retWrapInfo.(*wrapping.ResponseWrapInfo) } return &ret, nil diff --git a/logical/system_view.go b/logical/system_view.go index b6ab14b1fc..e13b63f287 100644 --- a/logical/system_view.go +++ b/logical/system_view.go @@ -6,6 +6,7 @@ import ( "github.com/hashicorp/vault/helper/consts" "github.com/hashicorp/vault/helper/pluginutil" + "github.com/hashicorp/vault/helper/wrapping" ) // SystemView exposes system configuration information in a safe way @@ -42,7 +43,7 @@ type SystemView interface { // ResponseWrapData wraps the given data in a cubbyhole and returns the // token used to unwrap. - ResponseWrapData(data map[string]interface{}, ttl time.Duration, jwt bool) (string, error) + ResponseWrapData(data map[string]interface{}, ttl time.Duration, jwt bool) (*wrapping.ResponseWrapInfo, error) // LookupPlugin looks into the plugin catalog for a plugin with the given // name. Returns a PluginRunner or an error if a plugin can not be found. @@ -87,8 +88,8 @@ func (d StaticSystemView) ReplicationState() consts.ReplicationState { return d.ReplicationStateVal } -func (d StaticSystemView) ResponseWrapData(data map[string]interface{}, ttl time.Duration, jwt bool) (string, error) { - return "", errors.New("ResponseWrapData is not implemented in StaticSystemView") +func (d StaticSystemView) ResponseWrapData(data map[string]interface{}, ttl time.Duration, jwt bool) (*wrapping.ResponseWrapInfo, error) { + return nil, errors.New("ResponseWrapData is not implemented in StaticSystemView") } func (d StaticSystemView) LookupPlugin(name string) (*pluginutil.PluginRunner, error) { diff --git a/vault/dynamic_system_view.go b/vault/dynamic_system_view.go index eb99f29c62..9302bfbc14 100644 --- a/vault/dynamic_system_view.go +++ b/vault/dynamic_system_view.go @@ -5,6 +5,7 @@ import ( "github.com/hashicorp/vault/helper/consts" "github.com/hashicorp/vault/helper/pluginutil" + "github.com/hashicorp/vault/helper/wrapping" "github.com/hashicorp/vault/logical" ) @@ -91,14 +92,14 @@ func (d dynamicSystemView) ReplicationState() consts.ReplicationState { // ResponseWrapData wraps the given data in a cubbyhole and returns the // token used to unwrap. -func (d dynamicSystemView) ResponseWrapData(data map[string]interface{}, ttl time.Duration, jwt bool) (string, error) { +func (d dynamicSystemView) ResponseWrapData(data map[string]interface{}, ttl time.Duration, jwt bool) (*wrapping.ResponseWrapInfo, error) { req := &logical.Request{ Operation: logical.CreateOperation, - Path: "sys/init", + Path: "sys/wrapping/wrap", } resp := &logical.Response{ - WrapInfo: &logical.ResponseWrapInfo{ + WrapInfo: &wrapping.ResponseWrapInfo{ TTL: ttl, }, Data: data, @@ -110,10 +111,10 @@ func (d dynamicSystemView) ResponseWrapData(data map[string]interface{}, ttl tim _, err := d.core.wrapInCubbyhole(req, resp) if err != nil { - return "", err + return nil, err } - return resp.WrapInfo.Token, nil + return resp.WrapInfo, nil } // LookupPlugin looks for a plugin with the given name in the plugin catalog. It diff --git a/vault/logical_system.go b/vault/logical_system.go index 843483449f..109100090c 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/vault/helper/consts" "github.com/hashicorp/vault/helper/parseutil" + "github.com/hashicorp/vault/helper/wrapping" "github.com/hashicorp/vault/logical" "github.com/hashicorp/vault/logical/framework" "github.com/mitchellh/mapstructure" @@ -2075,7 +2076,7 @@ func (b *SystemBackend) handleWrappingRewrap( Data: map[string]interface{}{ "response": response, }, - WrapInfo: &logical.ResponseWrapInfo{ + WrapInfo: &wrapping.ResponseWrapInfo{ TTL: time.Duration(creationTTL), }, }, nil diff --git a/vault/request_handling.go b/vault/request_handling.go index ad37b5aee0..1326ef518a 100644 --- a/vault/request_handling.go +++ b/vault/request_handling.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/vault/helper/jsonutil" "github.com/hashicorp/vault/helper/policyutil" "github.com/hashicorp/vault/helper/strutil" + "github.com/hashicorp/vault/helper/wrapping" "github.com/hashicorp/vault/logical" ) @@ -216,7 +217,7 @@ func (c *Core) handleRequest(req *logical.Request) (retResp *logical.Response, r } if wrapTTL > 0 { - resp.WrapInfo = &logical.ResponseWrapInfo{ + resp.WrapInfo = &wrapping.ResponseWrapInfo{ TTL: wrapTTL, Format: wrapFormat, } @@ -361,7 +362,7 @@ func (c *Core) handleLoginRequest(req *logical.Request) (*logical.Response, *log } if wrapTTL > 0 { - resp.WrapInfo = &logical.ResponseWrapInfo{ + resp.WrapInfo = &wrapping.ResponseWrapInfo{ TTL: wrapTTL, Format: wrapFormat, }