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

implement /state on alpha; login required if ACL enabled on alpha; al… #4435

Merged
merged 11 commits into from
Dec 23, 2019
25 changes: 25 additions & 0 deletions dgraph/cmd/alpha/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,30 @@ func healthCheck(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write(data)
}

func stateHandler(w http.ResponseWriter, r *http.Request) {
var err error
x.AddCorsHeaders(w)
w.Header().Set("Content-Type", "application/json")

ctx := context.Background()
ctx = attachAccessJwt(ctx, r)

var aResp *api.Response
if aResp, err = (&edgraph.Server{}).State(ctx); err != nil {
x.SetStatus(w, x.Error, err.Error())
return
}
if aResp == nil {
x.SetStatus(w, x.ErrorNoData, "No state information available.")
return
}

if _, err = w.Write(aResp.Json); err != nil {
x.SetStatus(w, x.Error, err.Error())
return
}
}

// storeStatsHandler outputs some basic stats for data store.
func storeStatsHandler(w http.ResponseWriter, r *http.Request) {
x.AddCorsHeaders(w)
Expand Down Expand Up @@ -390,6 +414,7 @@ func setupServer() {
http.HandleFunc("/commit", commitHandler)
http.HandleFunc("/alter", alterHandler)
http.HandleFunc("/health", healthCheck)
http.HandleFunc("/state", stateHandler)

// TODO: Figure out what this is for?
http.HandleFunc("/debug/store", storeStatsHandler)
Expand Down
5 changes: 5 additions & 0 deletions edgraph/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,8 @@ func authorizeQuery(ctx context.Context, parsedReq *gql.Result) error {
// always allow access
return nil
}

func authorizeState(ctx context.Context) error {
// always allow access
return nil
}
30 changes: 30 additions & 0 deletions edgraph/access_ee.go
Original file line number Diff line number Diff line change
Expand Up @@ -721,3 +721,33 @@ func authorizeQuery(ctx context.Context, parsedReq *gql.Result) error {

return err
}

// authorizeState authorizes the State operation
func authorizeState(ctx context.Context) error {
if len(worker.Config.HmacSecret) == 0 {
// the user has not turned on the acl feature
return nil
}

var userID string
// doAuthorizeState checks if the user is authorized to perform this API request
doAuthorizeState := func() error {
userData, err := extractUserAndGroups(ctx)
switch {
case err == errNoJwt:
return status.Error(codes.PermissionDenied, err.Error())
case err != nil:
return status.Error(codes.Unauthenticated, err.Error())
default:
userID = userData[0]
if userID == x.GrootId {
return nil
}
// Deny non groot users.
return status.Error(codes.PermissionDenied, fmt.Sprintf("User is '%v'. "+
"Only User '%v' is authorized.", userID, x.GrootId))
}
}

return doAuthorizeState()
}
34 changes: 34 additions & 0 deletions edgraph/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package edgraph

import (
"bytes"
"encoding/json"
"math"
"sort"
Expand All @@ -39,6 +40,7 @@ import (
"github.com/dgraph-io/dgraph/types/facets"
"github.com/dgraph-io/dgraph/worker"
"github.com/dgraph-io/dgraph/x"
"github.com/gogo/protobuf/jsonpb"
"github.com/golang/glog"
"github.com/pkg/errors"
"golang.org/x/net/context"
Expand Down Expand Up @@ -580,6 +582,38 @@ type queryContext struct {
span *trace.Span
}

// State handles state requests
func (s *Server) State(ctx context.Context) (*api.Response, error) {
return s.doState(ctx, NeedAuthorize)
}

func (s *Server) doState(ctx context.Context, authorize int) (
*api.Response, error) {

if ctx.Err() != nil {
return nil, ctx.Err()
}

if authorize == NeedAuthorize {
if err := authorizeState(ctx); err != nil {
return nil, err
}
}

ms := worker.GetMembershipState()
if ms == nil {
return nil, errors.Errorf("No membership state found")
}

m := jsonpb.Marshaler{}
var jsonState bytes.Buffer
if err := m.Marshal(&jsonState, ms); err != nil {
return nil, errors.Errorf("Error marshalling state information to JSON")
}

return &api.Response{Json: jsonState.Bytes()}, nil
}

// Query handles queries or mutations
func (s *Server) Query(ctx context.Context, req *api.Request) (*api.Response, error) {
return s.doQuery(ctx, req, NeedAuthorize)
Expand Down