initial local commit

This commit is contained in:
Laura Bennett 2016-07-23 21:46:28 -04:00
parent 9bb89431dc
commit e5737b6789
8 changed files with 70 additions and 25 deletions

View File

@ -10,53 +10,56 @@ import (
// 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 {
// Id is the uuid associated with each request
ID string `json:"id" structs:"id" mapstructure:"id"`
// Operation is the requested operation type
Operation Operation
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.
Path string
Path string `json:"path" structs:"path" mapstructure:"path"`
// Request data is an opaque map that must have string keys.
Data map[string]interface{}
Data map[string]interface{} `json:"map" structs:"data" mapstructure:"data"`
// Storage can be used to durably store and retrieve state.
Storage Storage
Storage Storage `json:"storage" structs:"storage" mapstructure:"storage"`
// Secret will be non-nil only for Revoke and Renew operations
// to represent the secret that was returned prior.
Secret *Secret
Secret *Secret `json:"secret" structs:"secret" mapstructure:"secret"`
// Auth will be non-nil only for Renew operations
// to represent the auth that was returned prior.
Auth *Auth
Auth *Auth `json:"auth" structs:"auth" mapstructure:"auth"`
// Connection will be non-nil only for credential providers to
// inspect the connection information and potentially use it for
// authentication/protection.
Connection *Connection
Connection *Connection `json:"connection" structs:"connection" mapstructure:"connection"`
// 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.
ClientToken string
ClientToken string `json:"client_token" structs:"client_token" mapstructure:"client_token"`
// 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.
DisplayName string
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.
MountPoint string
MountPoint string `json:"mount_point" structs:"mount_point" mapstructure:"mount_point"`
// WrapTTL contains the requested TTL of the token used to wrap the
// response in a cubbyhole.
WrapTTL time.Duration
WrapTTL time.Duration `json:"wrap_ttl" struct:"wrap_ttl" mapstructure:"wrap_ttl"`
}
// Get returns a data field and guards for nil Data

View File

@ -31,51 +31,51 @@ const (
type WrapInfo struct {
// Setting to non-zero specifies that the response should be wrapped.
// Specifies the desired TTL of the wrapping token.
TTL time.Duration
TTL time.Duration `json:"ttl" structs:"ttl" mapstructure:"ttl"`
// The token containing the wrapped response
Token string
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
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
WrappedAccessor string `json:"wrapped_accessor" structs:"wrapped_accessor" mapstructure:"wrapped_accessor"`
}
// 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 {
// Secret, if not nil, denotes that this response represents a secret.
Secret *Secret
Secret *Secret `json:"secret" structs:"secret" mapstructure:"secret"`
// Auth, if not nil, contains the authentication information for
// this response. This is only checked and means something for
// credential backends.
Auth *Auth
Auth *Auth `json:"auth" structs:"auth" mapstructure:"auth"`
// 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.
Data map[string]interface{}
Data map[string]interface{} `json:"data" structs:"data" mapstructure:"data"`
// 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
Redirect string `json:"redirect" structs:"redirect" mapstructure:"redirect"`
// 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
warnings []string `json:"warnings" structs:"warnings" mapstructure:"warnings"`
// Information for wrapping the response in a cubbyhole
WrapInfo *WrapInfo
WrapInfo *WrapInfo `json:"wrap_info" structs:"wrap_info" mapstructure:"wrap_info"`
}
func init() {

View File

@ -11,6 +11,7 @@ import (
"time"
"github.com/armon/go-metrics"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/audit"
"github.com/hashicorp/vault/helper/jsonutil"
@ -351,17 +352,24 @@ func (a *AuditBroker) GetHash(name string, input string) (string, error) {
// LogRequest is used to ensure all the audit backends have an opportunity to
// log the given request and that *at least one* succeeds.
func (a *AuditBroker) LogRequest(auth *logical.Auth, req *logical.Request, outerErr error) (reterr error) {
func (a *AuditBroker) LogRequest(auth *logical.Auth, req *logical.Request, outerErr error) (retErr error) {
defer metrics.MeasureSince([]string{"audit", "log_request"}, time.Now())
a.l.RLock()
defer a.l.RUnlock()
defer func() {
if r := recover(); r != nil {
a.logger.Printf("[ERR] audit: panic logging: req path: %s", req.Path)
reterr = fmt.Errorf("panic generating audit log")
retErr = multierror.Append(retErr, fmt.Errorf("panic generating audit log"))
}
}()
// All logged requests must have an identifier
if req.ID == "" {
a.logger.Printf("[ERR] audit: missing identifier in request object: %s", req.Path)
retErr = multierror.Append(retErr, fmt.Errorf("missing identifier in request object: %s", req.Path))
return
}
// Ensure at least one backend logs
anyLogged := false
for name, be := range a.backends {
@ -375,7 +383,8 @@ func (a *AuditBroker) LogRequest(auth *logical.Auth, req *logical.Request, outer
}
}
if !anyLogged && len(a.backends) > 0 {
return fmt.Errorf("no audit backend succeeded in logging the request")
retErr = multierror.Append(retErr, fmt.Errorf("no audit backend succeeded in logging the request"))
return
}
return nil
}

View File

@ -10,6 +10,7 @@ import (
"errors"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/audit"
"github.com/hashicorp/vault/logical"
)
@ -223,9 +224,17 @@ func TestAuditBroker_LogRequest(t *testing.T) {
Operation: logical.ReadOperation,
Path: "sys/mounts",
}
// Create an identifier for the request to verify against
var err error
req.ID, err = uuid.GenerateUUID()
if err != nil {
t.Fatalf("failed to generate identifier for the request: path%s err: %v", req.Path, err)
}
reqErrs := errors.New("errs")
err := b.LogRequest(auth, req, reqErrs)
err = b.LogRequest(auth, req, reqErrs)
if err != nil {
t.Fatalf("err: %v", err)
}

View File

@ -708,6 +708,12 @@ func (c *Core) sealInitCommon(req *logical.Request) (retErr error) {
return retErr
}
// Create an identifier for the request
var err error
req.ID, err = uuid.GenerateUUID()
if err != nil {
return fmt.Errorf("failed to generate identifier for the request: path: %s err: %v", req.Path, err)
}
// Validate the token is a root token
acl, te, err := c.fetchACLandTokenEntry(req)
if err != nil {

View File

@ -1153,6 +1153,12 @@ func TestCore_StepDown(t *testing.T) {
Path: "sys/step-down",
}
// Create an identifier for the request
req.ID, err = uuid.GenerateUUID()
if err != nil {
t.Fatalf("failed to generate identifier for the request: path: %s err: %v", req.Path, err)
}
// Step down core
err = core.StepDown(req)
if err != nil {

View File

@ -2,12 +2,14 @@ package vault
import (
"encoding/json"
"fmt"
"sort"
"strings"
"time"
"github.com/armon/go-metrics"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/helper/strutil"
"github.com/hashicorp/vault/logical"
)
@ -35,6 +37,12 @@ func (c *Core) HandleRequest(req *logical.Request) (resp *logical.Response, err
return logical.ErrorResponse("cannot write to a path ending in '/'"), nil
}
// Create an identifier for the request
req.ID, err = uuid.GenerateUUID()
if err != nil {
return nil, fmt.Errorf("failed to generate identifier for the request: path %s err %v", req.Path, err)
}
var auth *logical.Auth
if c.router.LoginPath(req.Path) {
resp, auth, err = c.handleLoginRequest(req)

View File

@ -248,11 +248,15 @@ func (r *Router) routeCommon(req *logical.Request, existenceCheck bool) (*logica
// Cache the pointer to the original connection object
originalConn := req.Connection
// Cache the identifier of the request
originalReqID := req.ID
// Reset the request before returning
defer func() {
req.Path = original
req.MountPoint = ""
req.Connection = originalConn
req.ID = originalReqID
req.Storage = nil
req.ClientToken = clientToken
}()