github.com/fanux/shipyard@v0.0.0-20161009071005-6515ce223235/controller/middleware/audit/audit.go (about)

     1  package audit
     2  
     3  import (
     4  	"errors"
     5  	"net/http"
     6  	"net/url"
     7  	"regexp"
     8  	"strings"
     9  	"time"
    10  
    11  	log "github.com/Sirupsen/logrus"
    12  	"github.com/shipyard/shipyard"
    13  	"github.com/shipyard/shipyard/controller/manager"
    14  )
    15  
    16  var (
    17  	ErrNoUserInToken = errors.New("no user sent in token")
    18  )
    19  
    20  type Auditor struct {
    21  	manager  manager.Manager
    22  	excludes []string
    23  }
    24  
    25  // parses username from auth token
    26  func getAuthUsername(r *http.Request) (string, error) {
    27  	authToken := r.Header.Get("X-Access-Token")
    28  
    29  	parts := strings.Split(authToken, ":")
    30  
    31  	if len(parts) != 2 {
    32  		return "", ErrNoUserInToken
    33  	}
    34  
    35  	return parts[0], nil
    36  }
    37  
    38  func filterURI(uri string) (string, error) {
    39  	u, err := url.Parse(uri)
    40  	if err != nil {
    41  		return "", err
    42  	}
    43  
    44  	return u.Path, nil
    45  }
    46  
    47  func NewAuditor(m manager.Manager, excludes []string) *Auditor {
    48  	return &Auditor{
    49  		manager:  m,
    50  		excludes: excludes,
    51  	}
    52  }
    53  
    54  func (a *Auditor) HandlerFuncWithNext(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
    55  	skipAudit := false
    56  
    57  	user, err := getAuthUsername(r)
    58  	if err != nil {
    59  		log.Errorf("audit error: %s", err)
    60  	}
    61  
    62  	path, err := filterURI(r.RequestURI)
    63  	if err != nil {
    64  		log.Errorf("audit path filter error: %s", err)
    65  	}
    66  
    67  	// check if excluded
    68  	for _, e := range a.excludes {
    69  		match, err := regexp.MatchString(e, path)
    70  		if err != nil {
    71  			log.Errorf("audit exclude error: %s", err)
    72  		}
    73  
    74  		if match {
    75  			skipAudit = true
    76  			break
    77  		}
    78  	}
    79  
    80  	if user != "" && path != "" && !skipAudit {
    81  		tagParts := strings.Split(path, "/")
    82  		tag := tagParts[1]
    83  
    84  		evt := &shipyard.Event{
    85  			Type:     "api",
    86  			Time:     time.Now(),
    87  			Username: user,
    88  			Message:  path,
    89  			Tags:     []string{"api", tag, strings.ToLower(r.Method)},
    90  		}
    91  
    92  		if err := a.manager.SaveEvent(evt); err != nil {
    93  			log.Errorf("error saving event: %s", err)
    94  		}
    95  	}
    96  
    97  	log.Debugf("%s: %s", r.Method, r.RequestURI)
    98  
    99  	// next must be called or middleware chain will break
   100  	if next != nil {
   101  		next(w, r)
   102  	}
   103  }