Skip to content

Commit

Permalink
Enforcement of permissions in api
Browse files Browse the repository at this point in the history
  • Loading branch information
javuto committed Mar 20, 2020
1 parent 2caf47c commit 75456a7
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 131 deletions.
4 changes: 4 additions & 0 deletions api/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ const (
contextAPI string = "osctrl-api-context"
)

const (
ctxUser = "user"
)

const (
adminLevel string = "admin"
userLevel string = "user"
Expand Down
30 changes: 14 additions & 16 deletions api/handlers-environments.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package main

import (
"fmt"
"log"
"net/http"

"github.com/gorilla/mux"
"github.com/jmpsec/osctrl/settings"
"github.com/jmpsec/osctrl/users"
"github.com/jmpsec/osctrl/utils"
)

Expand All @@ -20,37 +22,34 @@ func apiEnvironmentHandler(w http.ResponseWriter, r *http.Request) {
incMetric(metricAPIEnvsReq)
utils.DebugHTTPDump(r, settingsmgr.DebugHTTP(settings.ServiceAPI), false)
vars := mux.Vars(r)
// Extract name
name, ok := vars["name"]
// Extract environment
environment, ok := vars["environment"]
if !ok {
apiErrorResponse(w, "error getting environment", http.StatusInternalServerError, nil)
incMetric(metricAPIEnvsErr)
apiErrorResponse(w, "error getting name", http.StatusInternalServerError, nil)
utils.HTTPResponse(w, utils.JSONApplicationUTF8, http.StatusInternalServerError, errorContent)
return
}
// Get context data and check access
ctx := r.Context().Value(contextKey(contextAPI)).(contextValue)
if !apiUsers.IsAdmin(ctx["user"]) {
if !apiUsers.CheckPermissions(ctx[ctxUser], users.EnvLevel, environment) {
apiErrorResponse(w, "no access", http.StatusForbidden, fmt.Errorf("attempt to use API by user %s", ctx[ctxUser]))
incMetric(metricAPIEnvsErr)
log.Printf("attempt to use API by user %s", ctx["user"])
apiErrorResponse(w, "no access", http.StatusForbidden, nil)
return
}
// Get environment by name
env, err := envs.Get(name)
env, err := envs.Get(environment)
if err != nil {
incMetric(metricAPIEnvsErr)
if err.Error() == "record not found" {
log.Printf("environment not found: %s", name)
apiErrorResponse(w, "environment not found", http.StatusNotFound, nil)
apiErrorResponse(w, "environment not found", http.StatusNotFound, err)
} else {
apiErrorResponse(w, "error getting environment", http.StatusInternalServerError, err)
}
incMetric(metricAPIEnvsErr)
return
}
// Serialize and serve JSON
if settingsmgr.DebugService(settings.ServiceAPI) {
log.Printf("DebugService: Returned environment %s", name)
log.Printf("DebugService: Returned environment %s", environment)
}
utils.HTTPResponse(w, utils.JSONApplicationUTF8, http.StatusOK, env)
incMetric(metricAPIEnvsOK)
Expand All @@ -62,17 +61,16 @@ func apiEnvironmentsHandler(w http.ResponseWriter, r *http.Request) {
utils.DebugHTTPDump(r, settingsmgr.DebugHTTP(settings.ServiceAPI), false)
// Get context data and check access
ctx := r.Context().Value(contextKey(contextAPI)).(contextValue)
if !apiUsers.IsAdmin(ctx["user"]) {
if !apiUsers.CheckPermissions(ctx[ctxUser], users.AdminLevel, users.NoEnvironment) {
apiErrorResponse(w, "no access", http.StatusForbidden, fmt.Errorf("attempt to use API by user %s", ctx[ctxUser]))
incMetric(metricAPIEnvsErr)
log.Printf("attempt to use API by user %s", ctx["user"])
apiErrorResponse(w, "no access", http.StatusForbidden, nil)
return
}
// Get platforms
envAll, err := envs.All()
if err != nil {
incMetric(metricAPIEnvsErr)
apiErrorResponse(w, "error getting environments", http.StatusInternalServerError, err)
incMetric(metricAPIEnvsErr)
return
}
// Serialize and serve JSON
Expand Down
35 changes: 17 additions & 18 deletions api/handlers-nodes.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package main

import (
"fmt"
"log"
"net/http"

"github.com/gorilla/mux"
"github.com/jmpsec/osctrl/settings"
"github.com/jmpsec/osctrl/users"
"github.com/jmpsec/osctrl/utils"
)

Expand All @@ -23,28 +25,27 @@ func apiNodeHandler(w http.ResponseWriter, r *http.Request) {
// Extract uuid
uuid, ok := vars["uuid"]
if !ok {
incMetric(metricAPINodesErr)
apiErrorResponse(w, "error getting uuid", http.StatusInternalServerError, nil)
return
}
// Get context data and check access
ctx := r.Context().Value(contextKey(contextAPI)).(contextValue)
if !apiUsers.IsAdmin(ctx["user"]) {
incMetric(metricAPINodesErr)
log.Printf("attempt to use API by user %s", ctx["user"])
apiErrorResponse(w, "no access", http.StatusForbidden, nil)
return
}
// Get node by UUID
// FIXME keep a cache of nodes by UUID
node, err := nodesmgr.GetByUUID(uuid)
if err != nil {
incMetric(metricAPINodesErr)
if err.Error() == "record not found" {
log.Printf("node not found: %s", uuid)
apiErrorResponse(w, "node not found", http.StatusNotFound, nil)
apiErrorResponse(w, "node not found", http.StatusNotFound, err)
} else {
apiErrorResponse(w, "error getting node", http.StatusInternalServerError, err)
}
incMetric(metricAPIEnvsErr)
return
}
// Get context data and check access
ctx := r.Context().Value(contextKey(contextAPI)).(contextValue)
if !apiUsers.CheckPermissions(ctx[ctxUser], users.EnvLevel, node.Environment) {
apiErrorResponse(w, "no access", http.StatusForbidden, fmt.Errorf("attempt to use API by user %s", ctx[ctxUser]))
incMetric(metricAPIEnvsErr)
return
}
// Serialize and serve JSON
Expand All @@ -61,23 +62,21 @@ func apiNodesHandler(w http.ResponseWriter, r *http.Request) {
utils.DebugHTTPDump(r, settingsmgr.DebugHTTP(settings.ServiceAPI), false)
// Get context data and check access
ctx := r.Context().Value(contextKey(contextAPI)).(contextValue)
if !apiUsers.IsAdmin(ctx["user"]) {
incMetric(metricAPINodesErr)
log.Printf("attempt to use API by user %s", ctx["user"])
apiErrorResponse(w, "no access", http.StatusForbidden, nil)
if !apiUsers.CheckPermissions(ctx[ctxUser], users.AdminLevel, users.NoEnvironment) {
apiErrorResponse(w, "no access", http.StatusForbidden, fmt.Errorf("attempt to use API by user %s", ctx[ctxUser]))
incMetric(metricAPIEnvsErr)
return
}
// Get nodes
nodes, err := nodesmgr.Gets("all", 0)
if err != nil {
incMetric(metricAPINodesErr)
apiErrorResponse(w, "error getting nodes", http.StatusInternalServerError, err)
incMetric(metricAPINodesErr)
return
}
if len(nodes) == 0 {
incMetric(metricAPINodesErr)
log.Printf("no nodes")
apiErrorResponse(w, "no nodes", http.StatusNotFound, nil)
incMetric(metricAPINodesErr)
return
}
// Serialize and serve JSON
Expand Down
11 changes: 6 additions & 5 deletions api/handlers-platforms.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package main

import (
"fmt"
"log"
"net/http"

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

Expand All @@ -20,17 +22,16 @@ func apiPlatformsHandler(w http.ResponseWriter, r *http.Request) {
utils.DebugHTTPDump(r, settingsmgr.DebugHTTP(settings.ServiceAPI), false)
// Get context data and check access
ctx := r.Context().Value(contextKey(contextAPI)).(contextValue)
if !apiUsers.IsAdmin(ctx["user"]) {
incMetric(metricAPIPlatformsErr)
log.Printf("attempt to use API by user %s", ctx["user"])
apiErrorResponse(w, "no access", http.StatusForbidden, nil)
if !apiUsers.CheckPermissions(ctx[ctxUser], users.AdminLevel, users.NoEnvironment) {
apiErrorResponse(w, "no access", http.StatusForbidden, fmt.Errorf("attempt to use API by user %s", ctx[ctxUser]))
incMetric(metricAPIEnvsErr)
return
}
// Get platforms
platforms, err := nodesmgr.GetAllPlatforms()
if err != nil {
incMetric(metricAPIPlatformsErr)
apiErrorResponse(w, "error getting platforms", http.StatusInternalServerError, err)
incMetric(metricAPIPlatformsErr)
return
}
// Serialize and serve JSON
Expand Down
Loading

0 comments on commit 75456a7

Please sign in to comment.