X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/07115948f7d6281d7d8dada4608f5b3c991a84c8..e9bfb6900e3340bfcdcea691466cd849ca7d9ffc:/lib/controller/fed_containers.go diff --git a/lib/controller/fed_containers.go b/lib/controller/fed_containers.go index 32ae25fc4b..7fd5b25ad2 100644 --- a/lib/controller/fed_containers.go +++ b/lib/controller/fed_containers.go @@ -9,8 +9,8 @@ import ( "encoding/json" "fmt" "io/ioutil" - "log" "net/http" + "strings" "git.curoverse.com/arvados.git/sdk/go/auth" "git.curoverse.com/arvados.git/sdk/go/httpserver" @@ -25,45 +25,89 @@ func remoteContainerRequestCreate( w http.ResponseWriter, req *http.Request) bool { - if effectiveMethod != "POST" || uuid != "" || remainder != "" || - *clusterId == "" || *clusterId == h.handler.Cluster.ClusterID { + if effectiveMethod != "POST" || uuid != "" || remainder != "" { return false } - defer req.Body.Close() - var request map[string]interface{} - err := json.NewDecoder(req.Body).Decode(&request) + // First make sure supplied token is valid. + creds := auth.NewCredentials() + creds.LoadTokensFromHTTPRequest(req) - containerRequest, ok := request["container_request"].(map[string]interface{}) - if !ok { - log.Printf("wah wah") + currentUser, err := h.handler.validateAPItoken(req, creds.Tokens[0]) + if err != nil { + httpserver.Error(w, err.Error(), http.StatusForbidden) + return true + } + + if *clusterId == "" { + *clusterId = h.handler.Cluster.ClusterID + } + + if strings.HasPrefix(currentUser.Authorization.UUID, h.handler.Cluster.ClusterID) && + *clusterId == h.handler.Cluster.ClusterID { + // local user submitting container request to local cluster return false } - // If runtime_token is not set, create a new token - if _, ok := containerRequest["runtime_token"]; !ok { - log.Printf("ok %v", ok) + if req.Header.Get("Content-Type") != "application/json" { + httpserver.Error(w, "Expected Content-Type: application/json, got "+req.Header.Get("Content-Type"), http.StatusBadRequest) + return true + } - // First make sure supplied token is valid. - creds := auth.NewCredentials() - creds.LoadTokensFromHTTPRequest(req) + originalBody := req.Body + defer originalBody.Close() + var request map[string]interface{} + err = json.NewDecoder(req.Body).Decode(&request) + if err != nil { + httpserver.Error(w, err.Error(), http.StatusBadRequest) + return true + } - currentUser, err := h.handler.validateAPItoken(req, creds.Tokens[0]) + crString, ok := request["container_request"].(string) + if ok { + var crJson map[string]interface{} + err := json.Unmarshal([]byte(crString), &crJson) if err != nil { - httpserver.Error(w, err.Error(), http.StatusForbidden) + httpserver.Error(w, err.Error(), http.StatusBadRequest) return true } + request["container_request"] = crJson + } + + containerRequest, ok := request["container_request"].(map[string]interface{}) + if !ok { + // Use toplevel object as the container_request object + containerRequest = request + } + + // If runtime_token is not set, create a new token + if _, ok := containerRequest["runtime_token"]; !ok { if len(currentUser.Authorization.Scopes) != 1 || currentUser.Authorization.Scopes[0] != "all" { - return false + httpserver.Error(w, "Token scope is not [all]", http.StatusForbidden) + return true } - newtok, err := h.handler.createAPItoken(req, currentUser.UUID, nil) - if err != nil { - httpserver.Error(w, err.Error(), http.StatusForbidden) - return true + if strings.HasPrefix(currentUser.Authorization.UUID, h.handler.Cluster.ClusterID) { + // Local user, submitting to a remote cluster. + // Create a new time-limited token. + newtok, err := h.handler.createAPItoken(req, currentUser.UUID, nil) + if err != nil { + httpserver.Error(w, err.Error(), http.StatusForbidden) + return true + } + containerRequest["runtime_token"] = newtok.TokenV2() + } else { + // Remote user. Container request will use the + // current token, minus the trailing portion + // (optional container uuid). + sp := strings.Split(creds.Tokens[0], "/") + if len(sp) >= 3 { + containerRequest["runtime_token"] = strings.Join(sp[0:3], "/") + } else { + containerRequest["runtime_token"] = creds.Tokens[0] + } } - containerRequest["runtime_token"] = newtok.TokenV2() } newbody, err := json.Marshal(request)