2015-03-15 20:52:43 +00:00
|
|
|
package logical
|
|
|
|
|
2015-10-07 21:21:41 +00:00
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
2016-05-02 02:39:45 +00:00
|
|
|
"time"
|
2015-10-07 21:21:41 +00:00
|
|
|
|
|
|
|
"github.com/mitchellh/copystructure"
|
|
|
|
)
|
|
|
|
|
2015-05-27 21:09:47 +00:00
|
|
|
const (
|
|
|
|
// HTTPContentType can be specified in the Data field of a Response
|
|
|
|
// so that the HTTP front end can specify a custom Content-Type associated
|
|
|
|
// with the HTTPRawBody. This can only be used for non-secrets, and should
|
|
|
|
// be avoided unless absolutely necessary, such as implementing a specification.
|
|
|
|
// The value must be a string.
|
|
|
|
HTTPContentType = "http_content_type"
|
|
|
|
|
|
|
|
// HTTPRawBody is the raw content of the HTTP body that goes with the HTTPContentType.
|
|
|
|
// This can only be specified for non-secrets, and should should be similarly
|
|
|
|
// avoided like the HTTPContentType. The value must be a byte slice.
|
|
|
|
HTTPRawBody = "http_raw_body"
|
|
|
|
|
2015-08-09 19:20:06 +00:00
|
|
|
// HTTPStatusCode is the response code of the HTTP body that goes with the HTTPContentType.
|
2015-05-27 21:09:47 +00:00
|
|
|
// This can only be specified for non-secrets, and should should be similarly
|
|
|
|
// avoided like the HTTPContentType. The value must be an integer.
|
|
|
|
HTTPStatusCode = "http_status_code"
|
|
|
|
)
|
|
|
|
|
2016-05-02 02:39:45 +00:00
|
|
|
type WrapInfo struct {
|
|
|
|
// Setting to non-zero specifies that the response should be wrapped.
|
|
|
|
// Specifies the desired TTL of the wrapping token.
|
|
|
|
Duration time.Duration
|
|
|
|
|
|
|
|
// The token containing the wrapped response
|
|
|
|
Token string
|
|
|
|
|
|
|
|
// The mount point of the backend, useful for further requests (such as
|
|
|
|
// logging in with the given credentials)
|
|
|
|
MountPoint string
|
|
|
|
}
|
|
|
|
|
2015-03-15 20:52:43 +00:00
|
|
|
// 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 {
|
2015-03-19 22:11:42 +00:00
|
|
|
// Secret, if not nil, denotes that this response represents a secret.
|
|
|
|
Secret *Secret
|
2015-03-15 20:52:43 +00:00
|
|
|
|
2015-03-30 21:23:32 +00:00
|
|
|
// Auth, if not nil, contains the authentication information for
|
|
|
|
// this response. This is only checked and means something for
|
|
|
|
// credential backends.
|
|
|
|
Auth *Auth
|
|
|
|
|
2015-03-19 22:11:42 +00:00
|
|
|
// Response data is an opaque map that must have string keys. For
|
|
|
|
// secrets, this data is sent down to the user as-is. To store internal
|
|
|
|
// data that you don't want the user to see, store it in
|
|
|
|
// Secret.InternalData.
|
2015-03-15 20:52:43 +00:00
|
|
|
Data map[string]interface{}
|
2015-03-31 00:56:24 +00:00
|
|
|
|
|
|
|
// Redirect is an HTTP URL to redirect to for further authentication.
|
|
|
|
// This is only valid for credential backends. This will be blanked
|
|
|
|
// for any logical backend and ignored.
|
|
|
|
Redirect string
|
2015-10-07 19:30:54 +00:00
|
|
|
|
|
|
|
// Warnings allow operations or backends to return warnings in response
|
|
|
|
// to user actions without failing the action outright.
|
|
|
|
// Making it private helps ensure that it is easy for various parts of
|
|
|
|
// Vault (backend, core, etc.) to add warnings without accidentally
|
|
|
|
// replacing what exists.
|
|
|
|
warnings []string
|
2016-05-02 02:39:45 +00:00
|
|
|
|
|
|
|
// Information for wrapping the response in a cubbyhole
|
|
|
|
WrapInfo WrapInfo
|
2015-10-07 19:30:54 +00:00
|
|
|
}
|
|
|
|
|
2015-10-07 21:21:41 +00:00
|
|
|
func init() {
|
|
|
|
copystructure.Copiers[reflect.TypeOf(Response{})] = func(v interface{}) (interface{}, error) {
|
|
|
|
input := v.(Response)
|
|
|
|
ret := Response{
|
|
|
|
Redirect: input.Redirect,
|
|
|
|
}
|
|
|
|
|
|
|
|
if input.Secret != nil {
|
|
|
|
retSec, err := copystructure.Copy(input.Secret)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error copying Secret: %v", err)
|
|
|
|
}
|
|
|
|
ret.Secret = retSec.(*Secret)
|
|
|
|
}
|
|
|
|
|
|
|
|
if input.Auth != nil {
|
|
|
|
retAuth, err := copystructure.Copy(input.Auth)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error copying Secret: %v", err)
|
|
|
|
}
|
|
|
|
ret.Auth = retAuth.(*Auth)
|
|
|
|
}
|
|
|
|
|
|
|
|
if input.Data != nil {
|
|
|
|
retData, err := copystructure.Copy(&input.Data)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error copying Secret: %v", err)
|
|
|
|
}
|
|
|
|
ret.Data = retData.(map[string]interface{})
|
|
|
|
}
|
|
|
|
|
|
|
|
if input.Warnings() != nil {
|
|
|
|
for _, warning := range input.Warnings() {
|
|
|
|
ret.AddWarning(warning)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &ret, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-07 19:41:25 +00:00
|
|
|
// AddWarning adds a warning into the response's warning list
|
2015-10-07 19:30:54 +00:00
|
|
|
func (r *Response) AddWarning(warning string) {
|
|
|
|
if r.warnings == nil {
|
|
|
|
r.warnings = make([]string, 0, 1)
|
|
|
|
}
|
|
|
|
r.warnings = append(r.warnings, warning)
|
|
|
|
}
|
|
|
|
|
2015-10-07 19:41:25 +00:00
|
|
|
// Warnings returns the list of warnings set on the response
|
|
|
|
func (r *Response) Warnings() []string {
|
2015-10-07 19:30:54 +00:00
|
|
|
return r.warnings
|
|
|
|
}
|
|
|
|
|
2015-10-07 19:41:25 +00:00
|
|
|
// ClearWarnings clears the response's warning list
|
2015-10-07 19:30:54 +00:00
|
|
|
func (r *Response) ClearWarnings() {
|
|
|
|
r.warnings = make([]string, 0, 1)
|
2015-03-15 20:52:43 +00:00
|
|
|
}
|
|
|
|
|
2015-03-20 16:59:48 +00:00
|
|
|
// IsError returns true if this response seems to indicate an error.
|
|
|
|
func (r *Response) IsError() bool {
|
|
|
|
return r != nil && len(r.Data) == 1 && r.Data["error"] != nil
|
2015-03-15 20:52:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// HelpResponse is used to format a help response
|
|
|
|
func HelpResponse(text string, seeAlso []string) *Response {
|
|
|
|
return &Response{
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"help": text,
|
|
|
|
"see_also": seeAlso,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ErrorResponse is used to format an error response
|
|
|
|
func ErrorResponse(text string) *Response {
|
|
|
|
return &Response{
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"error": text,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2015-03-15 21:26:48 +00:00
|
|
|
|
|
|
|
// ListResponse is used to format a response to a list operation.
|
|
|
|
func ListResponse(keys []string) *Response {
|
2016-01-14 19:18:27 +00:00
|
|
|
resp := &Response{
|
|
|
|
Data: map[string]interface{}{},
|
|
|
|
}
|
2016-01-19 22:06:24 +00:00
|
|
|
if len(keys) != 0 {
|
2016-01-14 19:18:27 +00:00
|
|
|
resp.Data["keys"] = keys
|
2015-03-15 21:26:48 +00:00
|
|
|
}
|
2016-01-14 19:18:27 +00:00
|
|
|
return resp
|
2015-03-15 21:26:48 +00:00
|
|
|
}
|