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
|
// 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
|
// MUST not be modified in anyway. They should be deep copied if this is
|
||||||
// a possibility.
|
// 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
|
// LogResponse is used to syncronously log a response. This is done after
|
||||||
// the request is processed but before the response is sent. The arguments
|
// the request is processed but before the response is sent. The arguments
|
||||||
|
|
|
@ -8,22 +8,29 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FormatJSON is a Formatter implementation that structuteres data into
|
// FormatJSON is a Formatter implementation that structures data into
|
||||||
// a JSON format.
|
// a JSON format.
|
||||||
type FormatJSON struct{}
|
type FormatJSON struct{}
|
||||||
|
|
||||||
func (f *FormatJSON) FormatRequest(
|
func (f *FormatJSON) FormatRequest(
|
||||||
w io.Writer,
|
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 is nil, make an empty one
|
||||||
if auth == nil {
|
if auth == nil {
|
||||||
auth = new(logical.Auth)
|
auth = new(logical.Auth)
|
||||||
}
|
}
|
||||||
|
if err == nil {
|
||||||
|
err = errors.New("")
|
||||||
|
}
|
||||||
|
|
||||||
// Encode!
|
// Encode!
|
||||||
enc := json.NewEncoder(w)
|
enc := json.NewEncoder(w)
|
||||||
return enc.Encode(&JSONRequestEntry{
|
return enc.Encode(&JSONRequestEntry{
|
||||||
Type: "request",
|
Type: "request",
|
||||||
|
Error: err.Error(),
|
||||||
|
|
||||||
Auth: JSONAuth{
|
Auth: JSONAuth{
|
||||||
DisplayName: auth.DisplayName,
|
DisplayName: auth.DisplayName,
|
||||||
|
@ -106,6 +113,7 @@ type JSONRequestEntry struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Auth JSONAuth `json:"auth"`
|
Auth JSONAuth `json:"auth"`
|
||||||
Request JSONRequest `json:"request"`
|
Request JSONRequest `json:"request"`
|
||||||
|
Error string `json:"error"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSONResponseEntry is the structure of a response audit log entry in JSON.
|
// 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.
|
// It is recommended that you pass data through Hash prior to formatting it.
|
||||||
type Formatter interface {
|
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
|
FormatResponse(io.Writer, *logical.Auth, *logical.Request, *logical.Response, error) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ type Backend struct {
|
||||||
f *os.File
|
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 {
|
if err := b.open(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ func (b *Backend) LogRequest(auth *logical.Auth, req *logical.Request) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var format audit.FormatJSON
|
var format audit.FormatJSON
|
||||||
return format.FormatRequest(b.f, auth, req)
|
return format.FormatRequest(b.f, auth, req, outerErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) LogResponse(
|
func (b *Backend) LogResponse(
|
||||||
|
|
|
@ -52,7 +52,7 @@ type Backend struct {
|
||||||
logRaw bool
|
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 {
|
if !b.logRaw {
|
||||||
// Copy the structures
|
// Copy the structures
|
||||||
cp, err := copystructure.Copy(auth)
|
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
|
// Encode the entry as JSON
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
var format audit.FormatJSON
|
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
|
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
|
// LogRequest is used to ensure all the audit backends have an opportunity to
|
||||||
// log the given request and that *at least one* succeeds.
|
// 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())
|
defer metrics.MeasureSince([]string{"audit", "log_request"}, time.Now())
|
||||||
a.l.RLock()
|
a.l.RLock()
|
||||||
defer a.l.RUnlock()
|
defer a.l.RUnlock()
|
||||||
|
@ -270,7 +270,7 @@ func (a *AuditBroker) LogRequest(auth *logical.Auth, req *logical.Request) error
|
||||||
anyLogged := false
|
anyLogged := false
|
||||||
for name, be := range a.backends {
|
for name, be := range a.backends {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
err := be.backend.LogRequest(auth, req)
|
err := be.backend.LogRequest(auth, req, outerErr)
|
||||||
metrics.MeasureSince([]string{"audit", name, "log_request"}, start)
|
metrics.MeasureSince([]string{"audit", name, "log_request"}, start)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.logger.Printf("[ERR] audit: backend '%s' failed to log request: %v", name, err)
|
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) {
|
func (c *Core) handleRequest(req *logical.Request) (*logical.Response, error) {
|
||||||
defer metrics.MeasureSince([]string{"core", "handle_request"}, time.Now())
|
defer metrics.MeasureSince([]string{"core", "handle_request"}, time.Now())
|
||||||
|
|
||||||
// Validate the token
|
// Validate the token
|
||||||
auth, err := c.checkToken(req.Operation, req.Path, req.ClientToken)
|
auth, err := c.checkToken(req.Operation, req.Path, req.ClientToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -387,6 +388,11 @@ func (c *Core) handleRequest(req *logical.Request) (*logical.Response, error) {
|
||||||
errType = logical.ErrInvalidRequest
|
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
|
return logical.ErrorResponse(err.Error()), errType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,7 +400,7 @@ func (c *Core) handleRequest(req *logical.Request) (*logical.Response, error) {
|
||||||
req.DisplayName = auth.DisplayName
|
req.DisplayName = auth.DisplayName
|
||||||
|
|
||||||
// Create an audit trail of the request
|
// 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",
|
c.logger.Printf("[ERR] core: failed to audit request (%#v): %v",
|
||||||
req, err)
|
req, err)
|
||||||
return nil, ErrInternalError
|
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())
|
defer metrics.MeasureSince([]string{"core", "handle_login_request"}, time.Now())
|
||||||
|
|
||||||
// Create an audit trail of the request, auth is not available on login requests
|
// 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",
|
c.logger.Printf("[ERR] core: failed to audit request (%#v): %v",
|
||||||
req, err)
|
req, err)
|
||||||
return nil, ErrInternalError
|
return nil, ErrInternalError
|
||||||
|
|
|
@ -86,7 +86,7 @@ func TestKeyCopy(key []byte) []byte {
|
||||||
|
|
||||||
type noopAudit struct{}
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -656,13 +656,13 @@ func (ts *TokenStore) handleLookup(
|
||||||
|
|
||||||
// Lookup the token
|
// Lookup the token
|
||||||
out, err := ts.Lookup(id)
|
out, err := ts.Lookup(id)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest
|
return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fast-path the not found case
|
|
||||||
if out == nil {
|
if out == nil {
|
||||||
return nil, nil
|
return logical.ErrorResponse("bad token"), logical.ErrPermissionDenied
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a response. We purposely omit the parent reference otherwise
|
// Generate a response. We purposely omit the parent reference otherwise
|
||||||
|
|
Loading…
Reference in New Issue