Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mixed changes mostly in admin #50

Merged
merged 1 commit into from
Mar 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 32 additions & 17 deletions admin/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,26 @@ import (
"context"
"log"
"net/http"
"strconv"
"strings"

"github.com/jmpsec/osctrl/settings"
"github.com/jmpsec/osctrl/users"
)

const (
adminLevel string = "admin"
userLevel string = "user"
)

const (
ctxUser = "user"
ctxEmail = "email"
ctxCSRF = "csrftoken"
ctxAdmin = "admin"
ctxLevel = "user"
)

// Helper to verify if user is an admin
func checkAdminLevel(level string) bool {
return (level == adminLevel)
Expand All @@ -30,11 +40,6 @@ func handlerAuthCheck(h http.Handler) http.Handler {
http.Redirect(w, r, "/login", http.StatusFound)
return
}
// Update metadata for the user
err := adminUsers.UpdateMetadata(session.IPAddress, session.UserAgent, session.Username)
if err != nil {
log.Printf("error updating metadata for user %s: %v", session.Username, err)
}
// Set middleware values
s := make(contextValue)
s["user"] = session.Username
Expand All @@ -45,6 +50,11 @@ func handlerAuthCheck(h http.Handler) http.Handler {
s["level"] = userLevel
}
ctx := context.WithValue(r.Context(), contextKey("session"), s)
// Update metadata for the user
err := adminUsers.UpdateMetadata(session.IPAddress, session.UserAgent, session.Username, s["csrftoken"])
if err != nil {
log.Printf("error updating metadata for user %s: %v", session.Username, err)
}
// Access granted
h.ServeHTTP(w, r.WithContext(ctx))
case settings.AuthSAML:
Expand Down Expand Up @@ -84,11 +94,6 @@ func handlerAuthCheck(h http.Handler) http.Handler {
return
}
}
// Update metadata for the user
err = adminUsers.UpdateMetadata(session.IPAddress, session.UserAgent, session.Username)
if err != nil {
log.Printf("error updating metadata for user %s: %v", session.Username, err)
}
// Set middleware values
s := make(contextValue)
s["user"] = session.Username
Expand All @@ -99,6 +104,11 @@ func handlerAuthCheck(h http.Handler) http.Handler {
s["level"] = userLevel
}
ctx := context.WithValue(r.Context(), contextKey("session"), s)
// Update metadata for the user
err = adminUsers.UpdateMetadata(session.IPAddress, session.UserAgent, session.Username, s["csrftoken"])
if err != nil {
log.Printf("error updating metadata for user %s: %v", session.Username, err)
}
// Access granted
samlMiddleware.RequireAccount(h).ServeHTTP(w, r.WithContext(ctx))
} else {
Expand All @@ -109,16 +119,15 @@ func handlerAuthCheck(h http.Handler) http.Handler {
email := r.Header.Get(headersConfig.TrustedPrefix + headersConfig.Email)
groups := strings.Split(r.Header.Get(headersConfig.TrustedPrefix+headersConfig.Groups), ",")
fullname := r.Header.Get(headersConfig.TrustedPrefix + headersConfig.DisplayName)

// A username is required to use this system
if username == "" {
http.Redirect(w, r, forbiddenPath, http.StatusBadRequest)
return
}

// Set middleware values
s := make(contextValue)
s["user"] = username

s["csrftoken"] = generateCSRF()
for _, group := range groups {
if group == headersConfig.AdminGroup {
s["level"] = adminLevel
Expand All @@ -129,20 +138,17 @@ func handlerAuthCheck(h http.Handler) http.Handler {
// We can't break because we might still find a higher permission level
}
}

// This user didn't present a group that has permission to use the service
if _, ok := s["level"]; !ok {
http.Redirect(w, r, forbiddenPath, http.StatusForbidden)
return
}

newUser, err := adminUsers.New(username, "", email, fullname, (s["level"] == adminLevel))
if err != nil {
log.Printf("Error with new user %s: %v", username, err)
http.Redirect(w, r, forbiddenPath, http.StatusFound)
return
}

if err := adminUsers.Create(newUser); err != nil {
log.Printf("Error creating user %s: %v", username, err)
http.Redirect(w, r, forbiddenPath, http.StatusFound)
Expand All @@ -151,9 +157,18 @@ func handlerAuthCheck(h http.Handler) http.Handler {
// _, session := sessionsmgr.CheckAuth(r)
// s["csrftoken"] = session.Values["csrftoken"].(string)
ctx := context.WithValue(r.Context(), contextKey("session"), s)

// Access granted
h.ServeHTTP(w, r.WithContext(ctx))
}
})
}

// Helper to prepare context based on the user
func prepareContext(user users.AdminUser) contextValue {
s := make(contextValue)
s[ctxUser] = user.Username
s[ctxEmail] = user.Email
s[ctxCSRF] = user.CSRFToken
s[ctxAdmin] = strconv.FormatBool(user.Admin)
return s
}
23 changes: 10 additions & 13 deletions admin/handlers-get.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,15 @@ import (
"strings"

"github.com/jmpsec/osctrl/carves"
"github.com/jmpsec/osctrl/utils"
"github.com/jmpsec/osctrl/settings"
"github.com/jmpsec/osctrl/environments"
"github.com/jmpsec/osctrl/settings"
"github.com/jmpsec/osctrl/utils"

"github.com/gorilla/mux"
)

const (
templatesFilesFolder string = "tmpl_admin"
ctxUser string = "user"
ctxLevel string = "level"
ctxCSRF string = "csrftoken"
)

// TemplateFiles for building UI layout
Expand Down Expand Up @@ -787,9 +784,9 @@ func enrollGETHandler(w http.ResponseWriter, r *http.Request) {
Title: envVar + " Enroll",
Metadata: templateMetadata(ctx, serviceName, serviceVersion),
EnvName: envVar,
EnrollExpiry: strings.ToUpper(inFutureTime(env.EnrollExpire)),
EnrollExpiry: strings.ToUpper(utils.InFutureTime(env.EnrollExpire)),
EnrollExpired: environments.IsItExpired(env.EnrollExpire),
RemoveExpiry: strings.ToUpper(inFutureTime(env.RemoveExpire)),
RemoveExpiry: strings.ToUpper(utils.InFutureTime(env.RemoveExpire)),
RemoveExpired: environments.IsItExpired(env.RemoveExpire),
QuickAddShell: shellQuickAdd,
QuickRemoveShell: shellQuickRemove,
Expand Down Expand Up @@ -826,10 +823,10 @@ func nodeHandler(w http.ResponseWriter, r *http.Request) {
}
// Custom functions to handle formatting
funcMap := template.FuncMap{
"pastTimeAgo": pastTimeAgo,
"jsonRawIndent": jsonRawIndent,
"statusLogsLink": statusLogsLink,
"resultLogsLink": resultLogsLink,
"pastFutureTimes": utils.PastFutureTimes,
"jsonRawIndent": jsonRawIndent,
"statusLogsLink": statusLogsLink,
"resultLogsLink": resultLogsLink,
}
// Prepare template
tempateFiles := NewTemplateFiles(templatesFilesFolder, "node.html").filepaths
Expand Down Expand Up @@ -1029,8 +1026,8 @@ func usersGETHandler(w http.ResponseWriter, r *http.Request) {
}
// Custom functions to handle formatting
funcMap := template.FuncMap{
"pastTimeAgo": pastTimeAgo,
"inFutureTime": inFutureTime,
"pastFutureTimes": utils.PastFutureTimes,
"inFutureTime": utils.InFutureTime,
}
// Prepare template
tempateFiles := NewTemplateFiles(templatesFilesFolder, "users.html").filepaths
Expand Down
40 changes: 22 additions & 18 deletions admin/handlers-tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ func tokensGETHandler(w http.ResponseWriter, r *http.Request) {
// Prepare data to be returned
returned = TokenJSON{
Token: user.APIToken,
Expires: user.TokenExpire.String(),
ExpiresTS: user.TokenExpire.String(),
Expires: utils.PastFutureTimes(user.TokenExpire),
ExpiresTS: utils.TimeTimestamp(user.TokenExpire),
}
}
// Serve JSON
Expand Down Expand Up @@ -88,7 +88,7 @@ func tokensPOSTHandler(w http.ResponseWriter, r *http.Request) {
log.Println("DebugService: Decoding POST body")
}
var t TokenRequest
response := TokenResponse{}
var response TokenResponse
if err := json.NewDecoder(r.Body).Decode(&t); err == nil {
// Check CSRF Token
if checkCSRFToken(ctx[ctxCSRF], t.CSRFToken) {
Expand All @@ -98,21 +98,25 @@ func tokensPOSTHandler(w http.ResponseWriter, r *http.Request) {
adminErrorResponse(w, "error getting user", http.StatusInternalServerError, err)
return
}
if user.Admin {
token, exp, err := adminUsers.CreateToken(user.Username, jwtConfig.HoursToExpire, jwtConfig.JWTSecret)
if err != nil {
adminErrorResponse(w, "error creating token", http.StatusInternalServerError, err)
return
}
if err = adminUsers.UpdateToken(user.Username, token, exp); err != nil {
adminErrorResponse(w, "error updating token", http.StatusInternalServerError, err)
return
}
response = TokenResponse{
Token: token,
ExpirationTS: exp.String(),
Expiration: exp.String(),
}
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Println("DebugService: Creating token")
}
token, exp, err := adminUsers.CreateToken(user.Username, jwtConfig.HoursToExpire, jwtConfig.JWTSecret)
if err != nil {
adminErrorResponse(w, "error creating token", http.StatusInternalServerError, err)
return
}
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Println("DebugService: Updating token")
}
if err := adminUsers.UpdateToken(user.Username, token, exp); err != nil {
adminErrorResponse(w, "error updating token", http.StatusInternalServerError, err)
return
}
response = TokenResponse{
Token: token,
ExpirationTS: utils.TimeTimestamp(exp),
Expiration: utils.PastFutureTimes(exp),
}
} else {
adminErrorResponse(w, "user not found", http.StatusNotFound, nil)
Expand Down
4 changes: 2 additions & 2 deletions admin/json-carves.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ func jsonCarvesHandler(w http.ResponseWriter, r *http.Request) {
Creator: q.Creator,
Path: data,
Created: CreationTimes{
Display: pastTimeAgo(q.CreatedAt),
Timestamp: pastTimestamp(q.CreatedAt),
Display: utils.PastFutureTimes(q.CreatedAt),
Timestamp: utils.TimeTimestamp(q.CreatedAt),
},
Status: status,
Progress: progress,
Expand Down
14 changes: 7 additions & 7 deletions admin/json-logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func jsonLogsHandler(w http.ResponseWriter, r *http.Request) {
}
// Extract parameter for seconds
// If parameter is not present or invalid, it defaults to 6 hours back
secondsBack := int64(sixHours)
secondsBack := int64(utils.SixHours)
seconds, ok := r.URL.Query()["seconds"]
if ok {
s, err := strconv.ParseInt(seconds[0], 10, 64)
Expand All @@ -108,8 +108,8 @@ func jsonLogsHandler(w http.ResponseWriter, r *http.Request) {
// Prepare data to be returned
for _, s := range statusLogs {
_c := CreationTimes{
Display: pastTimeAgo(s.CreatedAt),
Timestamp: pastTimestamp(s.CreatedAt),
Display: utils.PastFutureTimes(s.CreatedAt),
Timestamp: utils.TimeTimestamp(s.CreatedAt),
}
_l := LogJSON{
Created: _c,
Expand All @@ -129,8 +129,8 @@ func jsonLogsHandler(w http.ResponseWriter, r *http.Request) {
for _, r := range resultLogs {
_l := LogJSON{
Created: CreationTimes{
Display: pastTimeAgo(r.CreatedAt),
Timestamp: pastTimestamp(r.CreatedAt),
Display: utils.PastFutureTimes(r.CreatedAt),
Timestamp: utils.TimeTimestamp(r.CreatedAt),
},
First: r.Name,
Second: string(r.Columns),
Expand Down Expand Up @@ -170,8 +170,8 @@ func jsonQueryLogsHandler(w http.ResponseWriter, r *http.Request) {
queryLogJSON := []QueryLogJSON{}
for _, q := range queryLogs {
_c := CreationTimes{
Display: pastTimeAgo(q.CreatedAt),
Timestamp: pastTimestamp(q.CreatedAt),
Display: utils.PastFutureTimes(q.CreatedAt),
Timestamp: utils.TimeTimestamp(q.CreatedAt),
}
_l := QueryLogJSON{
Created: _c,
Expand Down
8 changes: 4 additions & 4 deletions admin/json-nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ func jsonEnvironmentHandler(w http.ResponseWriter, r *http.Request) {
Version: n.PlatformVersion,
Osquery: n.OsqueryVersion,
LastSeen: CreationTimes{
Display: pastTimeAgo(n.UpdatedAt),
Timestamp: pastTimestamp(n.UpdatedAt),
Display: utils.PastFutureTimes(n.UpdatedAt),
Timestamp: utils.TimeTimestamp(n.UpdatedAt),
},
}
nJSON = append(nJSON, nj)
Expand Down Expand Up @@ -150,8 +150,8 @@ func jsonPlatformHandler(w http.ResponseWriter, r *http.Request) {
Version: n.PlatformVersion,
Osquery: n.OsqueryVersion,
LastSeen: CreationTimes{
Display: pastTimeAgo(n.UpdatedAt),
Timestamp: pastTimestamp(n.UpdatedAt),
Display: utils.PastFutureTimes(n.UpdatedAt),
Timestamp: utils.TimeTimestamp(n.UpdatedAt),
},
}
nJSON = append(nJSON, nj)
Expand Down
4 changes: 2 additions & 2 deletions admin/json-queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ func jsonQueryHandler(w http.ResponseWriter, r *http.Request) {
Creator: q.Creator,
Query: data,
Created: CreationTimes{
Display: pastTimeAgo(q.CreatedAt),
Timestamp: pastTimestamp(q.CreatedAt),
Display: utils.PastFutureTimes(q.CreatedAt),
Timestamp: utils.TimeTimestamp(q.CreatedAt),
},
Status: status,
Progress: progress,
Expand Down
2 changes: 1 addition & 1 deletion admin/static/js/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function refreshUserToken() {
sendPostRequest(data, '/tokens/' + _username + '/refresh', '', false, function (data) {
console.log(data);
$("#user_api_token").val(data.token);
$("#user_token_expiration").val(data.exp_ts);
$("#user_token_expiration").val(data.expiration);
$("#refreshTokenButton").prop("disabled", false);
$("#refreshTokenButton").text('Refresh');
});
Expand Down
Loading