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

Permissions in templates and refactor #53

Merged
merged 1 commit into from
Mar 20, 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
87 changes: 25 additions & 62 deletions admin/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"log"
"net/http"
"strconv"
"strings"

"github.com/jmpsec/osctrl/settings"
Expand All @@ -14,65 +13,37 @@ import (
const (
adminLevel string = "admin"
userLevel string = "user"
queryLevel string = "query"
carveLevel string = "carve"
)

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

// Helper to verify if user is an admin
func checkAdminLevel(user users.AdminUser) bool {
return user.Admin
}

// Helper to check if query access is granted
func checkQueryLevel(permissions users.UserPermissions) bool {
return permissions.Query
}

// Helper to check if carve access is granted
func checkCarveLevel(permissions users.UserPermissions) bool {
return permissions.Carve
}

// Helper to check if environment access is granted
func checkEnvironmentLevel(permissions users.UserPermissions, environment string) bool {
return permissions.Environments[environment]
}

// Helper to check permissions for a user
func checkPermissions(username string, query, carve, env bool, environment string) bool {
exist, user := adminUsers.ExistsGet(username)
if !exist {
return false
}
// Admin always have access
// Helper to convert permissions for a user to a level for context
func levelPermissions(user users.AdminUser) string {
if user.Admin {
return true
return adminLevel
}
perms, err := adminUsers.ConvertPermissions(user.Permissions.RawMessage)
if err != nil {
log.Printf("error converting permissions %v", err)
return false
return userLevel
}
// Check for query access
if query {
return checkQueryLevel(perms)
if perms.Query {
return queryLevel
}
// Check for carve access
if carve {
return checkCarveLevel(perms)
}
// Check for environment access
if env {
return checkEnvironmentLevel(perms, environment)
if perms.Carve {
return carveLevel
}
// At this point, no access granted
return false
return userLevel
}

// Handler to check access to a resource based on the authentication enabled
Expand All @@ -88,13 +59,9 @@ func handlerAuthCheck(h http.Handler) http.Handler {
}
// Set middleware values
s := make(contextValue)
s["user"] = session.Username
s["csrftoken"] = session.Values["csrftoken"].(string)
if session.Values["admin"].(bool) {
s["level"] = adminLevel
} else {
s["level"] = userLevel
}
s[ctxUser] = session.Username
s[ctxCSRF] = session.Values[ctxCSRF].(string)
s[ctxLevel] = session.Values[ctxLevel].(string)
ctx := context.WithValue(r.Context(), contextKey("session"), s)
// Update metadata for the user
err := adminUsers.UpdateMetadata(session.IPAddress, session.UserAgent, session.Username, s["csrftoken"])
Expand Down Expand Up @@ -142,13 +109,9 @@ func handlerAuthCheck(h http.Handler) http.Handler {
}
// Set middleware values
s := make(contextValue)
s["user"] = session.Username
s["csrftoken"] = session.Values["csrftoken"].(string)
if session.Values["admin"].(bool) {
s["level"] = adminLevel
} else {
s["level"] = userLevel
}
s[ctxUser] = session.Username
s[ctxCSRF] = session.Values[ctxCSRF].(string)
s[ctxLevel] = session.Values[ctxLevel].(string)
ctx := context.WithValue(r.Context(), contextKey("session"), s)
// Update metadata for the user
err = adminUsers.UpdateMetadata(session.IPAddress, session.UserAgent, session.Username, s["csrftoken"])
Expand All @@ -172,24 +135,24 @@ func handlerAuthCheck(h http.Handler) http.Handler {
}
// Set middleware values
s := make(contextValue)
s["user"] = username
s["csrftoken"] = generateCSRF()
s[ctxUser] = username
s[ctxCSRF] = generateCSRF()
for _, group := range groups {
if group == headersConfig.AdminGroup {
s["level"] = adminLevel
s[ctxLevel] = adminLevel
// We can break because there is no greater permission level
break
} else if group == headersConfig.UserGroup {
s["level"] = userLevel
s[ctxLevel] = userLevel
// 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 {
if _, ok := s[ctxLevel]; !ok {
http.Redirect(w, r, forbiddenPath, http.StatusForbidden)
return
}
newUser, err := adminUsers.New(username, "", email, fullname, (s["level"] == adminLevel))
newUser, err := adminUsers.New(username, "", email, fullname, (s[ctxLevel] == adminLevel))
if err != nil {
log.Printf("Error with new user %s: %v", username, err)
http.Redirect(w, r, forbiddenPath, http.StatusFound)
Expand All @@ -215,6 +178,6 @@ func prepareContext(user users.AdminUser) contextValue {
s[ctxUser] = user.Username
s[ctxEmail] = user.Email
s[ctxCSRF] = user.CSRFToken
s[ctxAdmin] = strconv.FormatBool(user.Admin)
s[ctxLevel] = levelPermissions(user)
return s
}
55 changes: 31 additions & 24 deletions admin/handlers-get.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/jmpsec/osctrl/carves"
"github.com/jmpsec/osctrl/environments"
"github.com/jmpsec/osctrl/settings"
"github.com/jmpsec/osctrl/users"
"github.com/jmpsec/osctrl/utils"

"github.com/gorilla/mux"
Expand Down Expand Up @@ -104,7 +105,7 @@ func environmentHandler(w http.ResponseWriter, r *http.Request) {
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !checkPermissions(ctx[ctxUser], false, false, true, env) {
if !adminUsers.CheckPermissions(ctx[ctxUser], users.EnvLevel, env) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricTokenErr)
return
Expand Down Expand Up @@ -185,7 +186,7 @@ func platformHandler(w http.ResponseWriter, r *http.Request) {
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !checkPermissions(ctx[ctxUser], false, false, false, "") {
if !adminUsers.CheckPermissions(ctx[ctxUser], users.AdminLevel, users.NoEnvironment) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricTokenErr)
return
Expand Down Expand Up @@ -246,7 +247,7 @@ func queryRunGETHandler(w http.ResponseWriter, r *http.Request) {
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !checkPermissions(ctx[ctxUser], true, false, false, "") {
if !adminUsers.CheckPermissions(ctx[ctxUser], users.QueryLevel, users.NoEnvironment) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricAdminErr)
return
Expand Down Expand Up @@ -322,7 +323,7 @@ func queryListGETHandler(w http.ResponseWriter, r *http.Request) {
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !checkPermissions(ctx[ctxUser], true, false, false, "") {
if !adminUsers.CheckPermissions(ctx[ctxUser], users.QueryLevel, users.NoEnvironment) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricAdminErr)
return
Expand Down Expand Up @@ -375,7 +376,7 @@ func carvesRunGETHandler(w http.ResponseWriter, r *http.Request) {
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !checkPermissions(ctx[ctxUser], false, true, false, "") {
if !adminUsers.CheckPermissions(ctx[ctxUser], users.CarveLevel, users.NoEnvironment) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricAdminErr)
return
Expand Down Expand Up @@ -445,7 +446,7 @@ func carvesListGETHandler(w http.ResponseWriter, r *http.Request) {
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !checkPermissions(ctx[ctxUser], false, true, false, "") {
if !adminUsers.CheckPermissions(ctx[ctxUser], users.CarveLevel, users.NoEnvironment) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricAdminErr)
return
Expand Down Expand Up @@ -498,7 +499,7 @@ func queryLogsHandler(w http.ResponseWriter, r *http.Request) {
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !checkPermissions(ctx[ctxUser], true, false, false, "") {
if !adminUsers.CheckPermissions(ctx[ctxUser], users.QueryLevel, users.NoEnvironment) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricAdminErr)
return
Expand Down Expand Up @@ -580,7 +581,7 @@ func carvesDetailsHandler(w http.ResponseWriter, r *http.Request) {
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !checkPermissions(ctx[ctxUser], false, true, false, "") {
if !adminUsers.CheckPermissions(ctx[ctxUser], users.CarveLevel, users.NoEnvironment) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricAdminErr)
return
Expand Down Expand Up @@ -691,7 +692,7 @@ func confGETHandler(w http.ResponseWriter, r *http.Request) {
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !checkPermissions(ctx[ctxUser], false, false, true, envVar) {
if !adminUsers.CheckPermissions(ctx[ctxUser], users.EnvLevel, envVar) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricAdminErr)
return
Expand Down Expand Up @@ -765,7 +766,7 @@ func enrollGETHandler(w http.ResponseWriter, r *http.Request) {
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !checkPermissions(ctx[ctxUser], false, false, true, envVar) {
if !adminUsers.CheckPermissions(ctx[ctxUser], users.EnvLevel, envVar) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricAdminErr)
return
Expand Down Expand Up @@ -860,6 +861,21 @@ func nodeHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("error getting table template: %v", err)
return
}
// Get node by UUID
node, err := nodesmgr.GetByUUID(uuid)
if err != nil {
incMetric(metricAdminErr)
log.Printf("error getting node %v", err)
return
}
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !adminUsers.CheckPermissions(ctx[ctxUser], users.EnvLevel, node.Environment) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricAdminErr)
return
}
// Get all environments
envAll, err := envs.All()
if err != nil {
Expand All @@ -874,15 +890,6 @@ func nodeHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("error getting platforms: %v", err)
return
}
// Get node by UUID
node, err := nodesmgr.GetByUUID(uuid)
if err != nil {
incMetric(metricAdminErr)
log.Printf("error getting node %v", err)
return
}
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Prepare template data
templateData := NodeTemplateData{
Title: "Node View " + node.Hostname,
Expand Down Expand Up @@ -910,7 +917,7 @@ func envsGETHandler(w http.ResponseWriter, r *http.Request) {
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !checkPermissions(ctx[ctxUser], false, false, false, "") {
if !adminUsers.CheckPermissions(ctx[ctxUser], users.AdminLevel, users.NoEnvironment) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricAdminErr)
return
Expand Down Expand Up @@ -963,7 +970,7 @@ func settingsGETHandler(w http.ResponseWriter, r *http.Request) {
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !checkPermissions(ctx[ctxUser], false, false, false, "") {
if !adminUsers.CheckPermissions(ctx[ctxUser], users.AdminLevel, users.NoEnvironment) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricAdminErr)
return
Expand Down Expand Up @@ -1043,7 +1050,7 @@ func usersGETHandler(w http.ResponseWriter, r *http.Request) {
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !checkPermissions(ctx[ctxUser], false, false, false, "") {
if !adminUsers.CheckPermissions(ctx[ctxUser], users.AdminLevel, users.NoEnvironment) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricAdminErr)
return
Expand Down Expand Up @@ -1117,7 +1124,7 @@ func permissionsGETHandler(w http.ResponseWriter, r *http.Request) {
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !checkPermissions(ctx[ctxUser], false, false, false, "") {
if !adminUsers.CheckPermissions(ctx[ctxUser], users.AdminLevel, users.NoEnvironment) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricAdminErr)
return
Expand All @@ -1141,7 +1148,7 @@ func carvesDownloadHandler(w http.ResponseWriter, r *http.Request) {
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Check permissions
if !checkPermissions(ctx[ctxUser], false, true, false, "") {
if !adminUsers.CheckPermissions(ctx[ctxUser], users.CarveLevel, users.NoEnvironment) {
log.Printf("%s has insuficient permissions", ctx[ctxUser])
incMetric(metricAdminErr)
return
Expand Down
Loading