open-vault/logical/request.go

196 lines
6.5 KiB
Go
Raw Normal View History

package logical
import (
"errors"
"fmt"
"time"
)
2017-01-04 21:44:03 +00:00
// RequestWrapInfo is a struct that stores information about desired response
// wrapping behavior
type RequestWrapInfo 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 format to use for the wrapped response; if not specified it's a bare
// token
Format string `json:"format" structs:"format" mapstructure:"format"`
}
// Request is a struct that stores the parameters and context
// of a request being made to Vault. It is used to abstract
// the details of the higher level request protocol from the handlers.
type Request struct {
2016-07-24 01:46:28 +00:00
// Id is the uuid associated with each request
ID string `json:"id" structs:"id" mapstructure:"id"`
// If set, the name given to the replication secondary where this request
// originated
ReplicationCluster string `json:"replication_cluster" structs:"replication_cluster", mapstructure:"replication_cluster"`
// Operation is the requested operation type
2016-07-24 01:46:28 +00:00
Operation Operation `json:"operation" structs:"operation" mapstructure:"operation"`
// Path is the part of the request path not consumed by the
// routing. As an example, if the original request path is "prod/aws/foo"
// and the AWS logical backend is mounted at "prod/aws/", then the
// final path is "foo" since the mount prefix is trimmed.
2016-07-24 01:46:28 +00:00
Path string `json:"path" structs:"path" mapstructure:"path"`
// Request data is an opaque map that must have string keys.
2016-07-24 01:46:28 +00:00
Data map[string]interface{} `json:"map" structs:"data" mapstructure:"data"`
// Storage can be used to durably store and retrieve state.
Storage Storage `json:"-"`
vault: clean up VaultID duplications, make secret responses clearer /cc @armon - This is a reasonably major refactor that I think cleans up a lot of the logic with secrets in responses. The reason for the refactor is that while implementing Renew/Revoke in logical/framework I found the existing API to be really awkward to work with. Primarily, we needed a way to send down internal data for Vault core to store since not all the data you need to revoke a key is always sent down to the user (for example the user than AWS key belongs to). At first, I was doing this manually in logical/framework with req.Storage, but this is going to be such a common event that I think its something core should assist with. Additionally, I think the added context for secrets will be useful in the future when we have a Vault API for returning orphaned out keys: we can also return the internal data that might help an operator. So this leads me to this refactor. I've removed most of the fields in `logical.Response` and replaced it with a single `*Secret` pointer. If this is non-nil, then the response represents a secret. The Secret struct encapsulates all the lease info and such. It also has some fields on it that are only populated at _request_ time for Revoke/Renew operations. There is precedent for this sort of behavior in the Go stdlib where http.Request/http.Response have fields that differ based on client/server. I copied this style. All core unit tests pass. The APIs fail for obvious reasons but I'll fix that up in the next commit.
2015-03-19 22:11:42 +00:00
// Secret will be non-nil only for Revoke and Renew operations
// to represent the secret that was returned prior.
2016-07-24 01:46:28 +00:00
Secret *Secret `json:"secret" structs:"secret" mapstructure:"secret"`
2015-03-24 18:09:25 +00:00
// Auth will be non-nil only for Renew operations
// to represent the auth that was returned prior.
2016-07-24 01:46:28 +00:00
Auth *Auth `json:"auth" structs:"auth" mapstructure:"auth"`
// Headers will contain the http headers from the request. This value will
// be used in the audit broker to ensure we are auditing only the allowed
// headers.
Headers map[string][]string `json:"headers" structs:"headers" mapstructure:"headers"`
// Connection will be non-nil only for credential providers to
// inspect the connection information and potentially use it for
// authentication/protection.
2016-07-24 01:46:28 +00:00
Connection *Connection `json:"connection" structs:"connection" mapstructure:"connection"`
2015-03-24 18:09:25 +00:00
// ClientToken is provided to the core so that the identity
// can be verified and ACLs applied. This value is passed
// through to the logical backends but after being salted and
// hashed.
2016-07-24 01:46:28 +00:00
ClientToken string `json:"client_token" structs:"client_token" mapstructure:"client_token"`
// ClientTokenAccessor is provided to the core so that the it can get
// logged as part of request audit logging.
ClientTokenAccessor string `json:"client_token_accessor" structs:"client_token_accessor" mapstructure:"client_token_accessor"`
// DisplayName is provided to the logical backend to help associate
// dynamic secrets with the source entity. This is not a sensitive
// name, but is useful for operators.
2016-07-24 01:46:28 +00:00
DisplayName string `json:"display_name" structs:"display_name" mapstructure:"display_name"`
// MountPoint is provided so that a logical backend can generate
// paths relative to itself. The `Path` is effectively the client
// request path with the MountPoint trimmed off.
2016-07-24 01:46:28 +00:00
MountPoint string `json:"mount_point" structs:"mount_point" mapstructure:"mount_point"`
2017-01-04 21:44:03 +00:00
// WrapInfo contains requested response wrapping parameters
WrapInfo *RequestWrapInfo `json:"wrap_info" structs:"wrap_info" mapstructure:"wrap_info"`
2017-03-01 17:39:42 +00:00
// For replication, contains the last WAL on the remote side after handling
// the request, used for best-effort avoidance of stale read-after-write
lastRemoteWAL uint64
}
// Get returns a data field and guards for nil Data
func (r *Request) Get(key string) interface{} {
if r.Data == nil {
return nil
}
return r.Data[key]
}
// GetString returns a data field as a string
func (r *Request) GetString(key string) string {
raw := r.Get(key)
s, _ := raw.(string)
return s
}
func (r *Request) GoString() string {
return fmt.Sprintf("*%#v", *r)
}
2017-03-01 17:39:42 +00:00
func (r *Request) LastRemoteWAL() uint64 {
return r.lastRemoteWAL
}
func (r *Request) SetLastRemoteWAL(last uint64) {
r.lastRemoteWAL = last
}
2015-03-19 19:20:25 +00:00
// RenewRequest creates the structure of the renew request.
func RenewRequest(
vault: clean up VaultID duplications, make secret responses clearer /cc @armon - This is a reasonably major refactor that I think cleans up a lot of the logic with secrets in responses. The reason for the refactor is that while implementing Renew/Revoke in logical/framework I found the existing API to be really awkward to work with. Primarily, we needed a way to send down internal data for Vault core to store since not all the data you need to revoke a key is always sent down to the user (for example the user than AWS key belongs to). At first, I was doing this manually in logical/framework with req.Storage, but this is going to be such a common event that I think its something core should assist with. Additionally, I think the added context for secrets will be useful in the future when we have a Vault API for returning orphaned out keys: we can also return the internal data that might help an operator. So this leads me to this refactor. I've removed most of the fields in `logical.Response` and replaced it with a single `*Secret` pointer. If this is non-nil, then the response represents a secret. The Secret struct encapsulates all the lease info and such. It also has some fields on it that are only populated at _request_ time for Revoke/Renew operations. There is precedent for this sort of behavior in the Go stdlib where http.Request/http.Response have fields that differ based on client/server. I copied this style. All core unit tests pass. The APIs fail for obvious reasons but I'll fix that up in the next commit.
2015-03-19 22:11:42 +00:00
path string, secret *Secret, data map[string]interface{}) *Request {
2015-03-19 19:20:25 +00:00
return &Request{
Operation: RenewOperation,
Path: path,
vault: clean up VaultID duplications, make secret responses clearer /cc @armon - This is a reasonably major refactor that I think cleans up a lot of the logic with secrets in responses. The reason for the refactor is that while implementing Renew/Revoke in logical/framework I found the existing API to be really awkward to work with. Primarily, we needed a way to send down internal data for Vault core to store since not all the data you need to revoke a key is always sent down to the user (for example the user than AWS key belongs to). At first, I was doing this manually in logical/framework with req.Storage, but this is going to be such a common event that I think its something core should assist with. Additionally, I think the added context for secrets will be useful in the future when we have a Vault API for returning orphaned out keys: we can also return the internal data that might help an operator. So this leads me to this refactor. I've removed most of the fields in `logical.Response` and replaced it with a single `*Secret` pointer. If this is non-nil, then the response represents a secret. The Secret struct encapsulates all the lease info and such. It also has some fields on it that are only populated at _request_ time for Revoke/Renew operations. There is precedent for this sort of behavior in the Go stdlib where http.Request/http.Response have fields that differ based on client/server. I copied this style. All core unit tests pass. The APIs fail for obvious reasons but I'll fix that up in the next commit.
2015-03-19 22:11:42 +00:00
Data: data,
Secret: secret,
2015-03-19 19:20:25 +00:00
}
}
// RenewAuthRequest creates the structure of the renew request for an auth.
func RenewAuthRequest(
path string, auth *Auth, data map[string]interface{}) *Request {
return &Request{
Operation: RenewOperation,
Path: path,
Data: data,
Auth: auth,
}
}
2015-03-19 19:20:25 +00:00
// RevokeRequest creates the structure of the revoke request.
func RevokeRequest(
vault: clean up VaultID duplications, make secret responses clearer /cc @armon - This is a reasonably major refactor that I think cleans up a lot of the logic with secrets in responses. The reason for the refactor is that while implementing Renew/Revoke in logical/framework I found the existing API to be really awkward to work with. Primarily, we needed a way to send down internal data for Vault core to store since not all the data you need to revoke a key is always sent down to the user (for example the user than AWS key belongs to). At first, I was doing this manually in logical/framework with req.Storage, but this is going to be such a common event that I think its something core should assist with. Additionally, I think the added context for secrets will be useful in the future when we have a Vault API for returning orphaned out keys: we can also return the internal data that might help an operator. So this leads me to this refactor. I've removed most of the fields in `logical.Response` and replaced it with a single `*Secret` pointer. If this is non-nil, then the response represents a secret. The Secret struct encapsulates all the lease info and such. It also has some fields on it that are only populated at _request_ time for Revoke/Renew operations. There is precedent for this sort of behavior in the Go stdlib where http.Request/http.Response have fields that differ based on client/server. I copied this style. All core unit tests pass. The APIs fail for obvious reasons but I'll fix that up in the next commit.
2015-03-19 22:11:42 +00:00
path string, secret *Secret, data map[string]interface{}) *Request {
2015-03-19 19:20:25 +00:00
return &Request{
Operation: RevokeOperation,
Path: path,
vault: clean up VaultID duplications, make secret responses clearer /cc @armon - This is a reasonably major refactor that I think cleans up a lot of the logic with secrets in responses. The reason for the refactor is that while implementing Renew/Revoke in logical/framework I found the existing API to be really awkward to work with. Primarily, we needed a way to send down internal data for Vault core to store since not all the data you need to revoke a key is always sent down to the user (for example the user than AWS key belongs to). At first, I was doing this manually in logical/framework with req.Storage, but this is going to be such a common event that I think its something core should assist with. Additionally, I think the added context for secrets will be useful in the future when we have a Vault API for returning orphaned out keys: we can also return the internal data that might help an operator. So this leads me to this refactor. I've removed most of the fields in `logical.Response` and replaced it with a single `*Secret` pointer. If this is non-nil, then the response represents a secret. The Secret struct encapsulates all the lease info and such. It also has some fields on it that are only populated at _request_ time for Revoke/Renew operations. There is precedent for this sort of behavior in the Go stdlib where http.Request/http.Response have fields that differ based on client/server. I copied this style. All core unit tests pass. The APIs fail for obvious reasons but I'll fix that up in the next commit.
2015-03-19 22:11:42 +00:00
Data: data,
Secret: secret,
2015-03-19 19:20:25 +00:00
}
}
// RollbackRequest creates the structure of the revoke request.
func RollbackRequest(path string) *Request {
return &Request{
Operation: RollbackOperation,
Path: path,
Data: make(map[string]interface{}),
}
}
// Operation is an enum that is used to specify the type
// of request being made
type Operation string
const (
2015-03-19 18:41:41 +00:00
// The operations below are called per path
CreateOperation Operation = "create"
ReadOperation = "read"
UpdateOperation = "update"
2015-03-19 18:41:41 +00:00
DeleteOperation = "delete"
ListOperation = "list"
HelpOperation = "help"
// The operations below are called globally, the path is less relevant.
RevokeOperation Operation = "revoke"
RenewOperation = "renew"
RollbackOperation = "rollback"
)
var (
// ErrUnsupportedOperation is returned if the operation is not supported
// by the logical backend.
ErrUnsupportedOperation = errors.New("unsupported operation")
// ErrUnsupportedPath is returned if the path is not supported
// by the logical backend.
ErrUnsupportedPath = errors.New("unsupported path")
// ErrInvalidRequest is returned if the request is invalid
ErrInvalidRequest = errors.New("invalid request")
2015-08-09 19:20:06 +00:00
// ErrPermissionDenied is returned if the client is not authorized
ErrPermissionDenied = errors.New("permission denied")
)