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 }