Implement CORS for the administrative interface.
This commit is contained in:
@@ -112,6 +112,9 @@ The fields are as follows:
|
|||||||
- `allowOrigin` is an array that contains the list of HTTP origins that
|
- `allowOrigin` is an array that contains the list of HTTP origins that
|
||||||
are allowed to access the server.
|
are allowed to access the server.
|
||||||
|
|
||||||
|
- `allowAdminOrigin` is like `allowOrigin`, but applies to the
|
||||||
|
administrative interface.
|
||||||
|
|
||||||
- `proxyURL`: if running behind a reverse proxy, this specifies the root
|
- `proxyURL`: if running behind a reverse proxy, this specifies the root
|
||||||
URL that will be visible outside the proxy.
|
URL that will be visible outside the proxy.
|
||||||
|
|
||||||
|
|||||||
+47
-9
@@ -104,6 +104,19 @@ func getJSON(w http.ResponseWriter, r *http.Request, v any) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func apiCORS(w http.ResponseWriter, r *http.Request, methods string) bool {
|
||||||
|
CheckOrigin(w, r, true)
|
||||||
|
if r.Method == "OPTIONS" {
|
||||||
|
w.Header().Set("Access-Control-Allow-Methods",
|
||||||
|
"OPTIONS, "+methods)
|
||||||
|
w.Header().Set("Access-Control-Allow-Headers",
|
||||||
|
"Authorization, Content-Type",
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func apiHandler(w http.ResponseWriter, r *http.Request) {
|
func apiHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if !strings.HasPrefix(r.URL.Path, "/galene-api/") {
|
if !strings.HasPrefix(r.URL.Path, "/galene-api/") {
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
@@ -112,11 +125,14 @@ func apiHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
first, kind, rest := splitPath(r.URL.Path[len("/galene-api"):])
|
first, kind, rest := splitPath(r.URL.Path[len("/galene-api"):])
|
||||||
if first == "/v0" && kind == ".stats" && rest == "" {
|
if first == "/v0" && kind == ".stats" && rest == "" {
|
||||||
|
if apiCORS(w, r, "HEAD, GET") {
|
||||||
|
return
|
||||||
|
}
|
||||||
if !checkAdmin(w, r) {
|
if !checkAdmin(w, r) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if r.Method != "HEAD" && r.Method != "GET" {
|
if r.Method != "HEAD" && r.Method != "GET" {
|
||||||
methodNotAllowed(w, "HEAD", "GET")
|
methodNotAllowed(w, "HEAD, GET")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set("cache-control", "no-cache")
|
w.Header().Set("cache-control", "no-cache")
|
||||||
@@ -139,11 +155,14 @@ func apiGroupHandler(w http.ResponseWriter, r *http.Request, pth string) {
|
|||||||
}
|
}
|
||||||
g := first[1:]
|
g := first[1:]
|
||||||
if g == "" && kind == "" {
|
if g == "" && kind == "" {
|
||||||
|
if apiCORS(w, r, "HEAD, GET") {
|
||||||
|
return
|
||||||
|
}
|
||||||
if !checkAdmin(w, r) {
|
if !checkAdmin(w, r) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if r.Method != "HEAD" && r.Method != "GET" {
|
if r.Method != "HEAD" && r.Method != "GET" {
|
||||||
methodNotAllowed(w, "HEAD", "GET")
|
methodNotAllowed(w, "HEAD, GET")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
groups, err := group.GetDescriptionNames()
|
groups, err := group.GetDescriptionNames()
|
||||||
@@ -178,6 +197,9 @@ func apiGroupHandler(w http.ResponseWriter, r *http.Request, pth string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if apiCORS(w, r, "HEAD, GET, PUT, DELETE") {
|
||||||
|
return
|
||||||
|
}
|
||||||
if !checkAdmin(w, r) {
|
if !checkAdmin(w, r) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -248,7 +270,7 @@ func apiGroupHandler(w http.ResponseWriter, r *http.Request, pth string) {
|
|||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
methodNotAllowed(w, "HEAD", "GET", "PUT", "DELETE")
|
methodNotAllowed(w, "HEAD, GET, PUT, DELETE")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,11 +280,14 @@ func usersHandler(w http.ResponseWriter, r *http.Request, g, pth string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if pth == "/" {
|
if pth == "/" {
|
||||||
|
if apiCORS(w, r, "HEAD, GET") {
|
||||||
|
return
|
||||||
|
}
|
||||||
if !checkAdmin(w, r) {
|
if !checkAdmin(w, r) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if r.Method != "HEAD" && r.Method != "GET" {
|
if r.Method != "HEAD" && r.Method != "GET" {
|
||||||
methodNotAllowed(w, "HEAD", "GET")
|
methodNotAllowed(w, "HEAD, GET")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
users, etag, err := group.GetUsers(g)
|
users, etag, err := group.GetUsers(g)
|
||||||
@@ -310,6 +335,9 @@ func specialUserHandler(w http.ResponseWriter, r *http.Request, g, pth string, w
|
|||||||
}
|
}
|
||||||
|
|
||||||
func userHandler(w http.ResponseWriter, r *http.Request, g, user string, wildcard bool) {
|
func userHandler(w http.ResponseWriter, r *http.Request, g, user string, wildcard bool) {
|
||||||
|
if apiCORS(w, r, "HEAD, GET, PUT, DELETE") {
|
||||||
|
return
|
||||||
|
}
|
||||||
if !checkAdmin(w, r) {
|
if !checkAdmin(w, r) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -378,11 +406,14 @@ func userHandler(w http.ResponseWriter, r *http.Request, g, user string, wildcar
|
|||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
methodNotAllowed(w, "HEAD", "GET", "PUT", "DELETE")
|
methodNotAllowed(w, "HEAD, GET, PUT, DELETE")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func passwordHandler(w http.ResponseWriter, r *http.Request, g, user string, wildcard bool) {
|
func passwordHandler(w http.ResponseWriter, r *http.Request, g, user string, wildcard bool) {
|
||||||
|
if apiCORS(w, r, "PUT, POST, DELETE") {
|
||||||
|
return
|
||||||
|
}
|
||||||
if !checkPasswordAdmin(w, r, g, user, wildcard) {
|
if !checkPasswordAdmin(w, r, g, user, wildcard) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -433,7 +464,7 @@ func passwordHandler(w http.ResponseWriter, r *http.Request, g, user string, wil
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
methodNotAllowed(w, "PUT", "POST", "DELETE")
|
methodNotAllowed(w, "PUT, POST, DELETE")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,6 +473,9 @@ type jwkset = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func keysHandler(w http.ResponseWriter, r *http.Request, g string) {
|
func keysHandler(w http.ResponseWriter, r *http.Request, g string) {
|
||||||
|
if apiCORS(w, r, "HEAD, GET") {
|
||||||
|
return
|
||||||
|
}
|
||||||
if !checkAdmin(w, r) {
|
if !checkAdmin(w, r) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -481,7 +515,7 @@ func keysHandler(w http.ResponseWriter, r *http.Request, g string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
methodNotAllowed(w, "PUT", "DELETE")
|
methodNotAllowed(w, "PUT, DELETE")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,9 +524,13 @@ func tokensHandler(w http.ResponseWriter, r *http.Request, g, pth string) {
|
|||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if apiCORS(w, r, "HEAD, GET, POST, PUT, DELETE") {
|
||||||
|
return
|
||||||
|
}
|
||||||
if !checkAdmin(w, r) {
|
if !checkAdmin(w, r) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that the group exists
|
// check that the group exists
|
||||||
_, err := group.GetDescription(g)
|
_, err := group.GetDescription(g)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -541,7 +579,7 @@ func tokensHandler(w http.ResponseWriter, r *http.Request, g, pth string) {
|
|||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
methodNotAllowed(w, "HEAD", "GET", "POST")
|
methodNotAllowed(w, "HEAD, GET, POST")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,6 +675,6 @@ func tokensHandler(w http.ResponseWriter, r *http.Request, g, pth string) {
|
|||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
methodNotAllowed(w, "HEAD", "GET", "PUT", "DELETE")
|
methodNotAllowed(w, "HEAD, GET, PUT, DELETE")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,15 +146,8 @@ func httpError(w http.ResponseWriter, err error) {
|
|||||||
http.StatusInternalServerError)
|
http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
func methodNotAllowed(w http.ResponseWriter, methods ...string) {
|
func methodNotAllowed(w http.ResponseWriter, methods string) {
|
||||||
ms := ""
|
w.Header().Set("Allow", "OPTIONS, " + methods)
|
||||||
for _, m := range methods {
|
|
||||||
if ms != "" {
|
|
||||||
ms = ms + ", "
|
|
||||||
}
|
|
||||||
ms = ms + m
|
|
||||||
}
|
|
||||||
w.Header().Set("Allow", ms)
|
|
||||||
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -178,7 +178,7 @@ func whipEndpointHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if r.Method != "POST" {
|
if r.Method != "POST" {
|
||||||
methodNotAllowed(w, "OPTIONS", "POST")
|
methodNotAllowed(w, "POST")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +323,7 @@ func whipResourceHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if r.Method != "PATCH" {
|
if r.Method != "PATCH" {
|
||||||
methodNotAllowed(w, "OPTIONS", "DELETE", "PATCH")
|
methodNotAllowed(w, "DELETE, PATCH")
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user