Logging authentication errors and bad token usage
This commit is contained in:
parent
c55f103c58
commit
4ec685dc1a
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue