Logging authentication errors and bad token usage

This commit is contained in:
Nate Brown 2015-06-18 18:30:18 -07:00
parent c55f103c58
commit 4ec685dc1a
9 changed files with 29 additions and 15 deletions

View File

@ -11,7 +11,7 @@ type Backend interface {
// request is authorized but before the request is executed. The arguments
// MUST not be modified in anyway. They should be deep copied if this is
// a possibility.
LogRequest(*logical.Auth, *logical.Request) error
LogRequest(*logical.Auth, *logical.Request, error) error
// LogResponse is used to syncronously log a response. This is done after
// the request is processed but before the response is sent. The arguments

View File

@ -8,22 +8,29 @@ import (
"errors"
)
// FormatJSON is a Formatter implementation that structuteres data into
// FormatJSON is a Formatter implementation that structures data into
// a JSON format.
type FormatJSON struct{}
func (f *FormatJSON) FormatRequest(
w io.Writer,
auth *logical.Auth, req *logical.Request) error {
auth *logical.Auth,
req *logical.Request,
err error) error {
// If auth is nil, make an empty one
if auth == nil {
auth = new(logical.Auth)
}
if err == nil {
err = errors.New("")
}
// Encode!
enc := json.NewEncoder(w)
return enc.Encode(&JSONRequestEntry{
Type: "request",
Error: err.Error(),
Auth: JSONAuth{
DisplayName: auth.DisplayName,
@ -106,6 +113,7 @@ type JSONRequestEntry struct {
Type string `json:"type"`
Auth JSONAuth `json:"auth"`
Request JSONRequest `json:"request"`
Error string `json:"error"`
}
// JSONResponseEntry is the structure of a response audit log entry in JSON.

View File

@ -12,6 +12,6 @@ import (
//
// It is recommended that you pass data through Hash prior to formatting it.
type Formatter interface {
FormatRequest(io.Writer, *logical.Auth, *logical.Request) error
FormatRequest(io.Writer, *logical.Auth, *logical.Request, error) error
FormatResponse(io.Writer, *logical.Auth, *logical.Request, *logical.Response, error) error
}

View File

@ -48,7 +48,7 @@ type Backend struct {
f *os.File
}
func (b *Backend) LogRequest(auth *logical.Auth, req *logical.Request) error {
func (b *Backend) LogRequest(auth *logical.Auth, req *logical.Request, outerErr error) error {
if err := b.open(); err != nil {
return err
}
@ -76,7 +76,7 @@ func (b *Backend) LogRequest(auth *logical.Auth, req *logical.Request) error {
}
var format audit.FormatJSON
return format.FormatRequest(b.f, auth, req)
return format.FormatRequest(b.f, auth, req, outerErr)
}
func (b *Backend) LogResponse(

View File

@ -52,7 +52,7 @@ type Backend struct {
logRaw bool
}
func (b *Backend) LogRequest(auth *logical.Auth, req *logical.Request) error {
func (b *Backend) LogRequest(auth *logical.Auth, req *logical.Request, outerErr error) error {
if !b.logRaw {
// Copy the structures
cp, err := copystructure.Copy(auth)
@ -79,7 +79,7 @@ func (b *Backend) LogRequest(auth *logical.Auth, req *logical.Request) error {
// Encode the entry as JSON
var buf bytes.Buffer
var format audit.FormatJSON
if err := format.FormatRequest(&buf, auth, req); err != nil {
if err := format.FormatRequest(&buf, auth, req, outerErr); err != nil {
return err
}

View File

@ -261,7 +261,7 @@ func (a *AuditBroker) IsRegistered(name string) bool {
// 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) error {
func (a *AuditBroker) LogRequest(auth *logical.Auth, req *logical.Request, outerErr error) error {
defer metrics.MeasureSince([]string{"audit", "log_request"}, time.Now())
a.l.RLock()
defer a.l.RUnlock()
@ -270,7 +270,7 @@ func (a *AuditBroker) LogRequest(auth *logical.Auth, req *logical.Request) error
anyLogged := false
for name, be := range a.backends {
start := time.Now()
err := be.backend.LogRequest(auth, req)
err := be.backend.LogRequest(auth, req, outerErr)
metrics.MeasureSince([]string{"audit", name, "log_request"}, start)
if err != nil {
a.logger.Printf("[ERR] audit: backend '%s' failed to log request: %v", name, err)

View File

@ -374,6 +374,7 @@ func (c *Core) HandleRequest(req *logical.Request) (resp *logical.Response, err
func (c *Core) handleRequest(req *logical.Request) (*logical.Response, error) {
defer metrics.MeasureSince([]string{"core", "handle_request"}, time.Now())
// Validate the token
auth, err := c.checkToken(req.Operation, req.Path, req.ClientToken)
if err != nil {
@ -387,6 +388,11 @@ func (c *Core) handleRequest(req *logical.Request) (*logical.Response, error) {
errType = logical.ErrInvalidRequest
}
if err := c.auditBroker.LogRequest(auth, req, err); err != nil {
c.logger.Printf("[ERR] core: failed to audit request (%#v): %v",
req, err)
}
return logical.ErrorResponse(err.Error()), errType
}
@ -394,7 +400,7 @@ func (c *Core) handleRequest(req *logical.Request) (*logical.Response, error) {
req.DisplayName = auth.DisplayName
// Create an audit trail of the request
if err := c.auditBroker.LogRequest(auth, req); err != nil {
if err := c.auditBroker.LogRequest(auth, req, errors.New("")); err != nil {
c.logger.Printf("[ERR] core: failed to audit request (%#v): %v",
req, err)
return nil, ErrInternalError
@ -473,7 +479,7 @@ func (c *Core) handleLoginRequest(req *logical.Request) (*logical.Response, erro
defer metrics.MeasureSince([]string{"core", "handle_login_request"}, time.Now())
// Create an audit trail of the request, auth is not available on login requests
if err := c.auditBroker.LogRequest(nil, req); err != nil {
if err := c.auditBroker.LogRequest(nil, req, errors.New("")); err != nil {
c.logger.Printf("[ERR] core: failed to audit request (%#v): %v",
req, err)
return nil, ErrInternalError

View File

@ -86,7 +86,7 @@ func TestKeyCopy(key []byte) []byte {
type noopAudit struct{}
func (n *noopAudit) LogRequest(a *logical.Auth, r *logical.Request) error {
func (n *noopAudit) LogRequest(a *logical.Auth, r *logical.Request, e error) error {
return nil
}

View File

@ -656,13 +656,13 @@ func (ts *TokenStore) handleLookup(
// Lookup the token
out, err := ts.Lookup(id)
if err != nil {
return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest
}
// Fast-path the not found case
if out == nil {
return nil, nil
return logical.ErrorResponse("bad token"), logical.ErrPermissionDenied
}
// Generate a response. We purposely omit the parent reference otherwise