Skip to content

Commit

Permalink
Removing the ACL feature from release/v1.0 (#3557)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lucas Wang authored Jun 13, 2019
1 parent ff5ee1e commit 1b98d81
Show file tree
Hide file tree
Showing 16 changed files with 6 additions and 1,466 deletions.
21 changes: 0 additions & 21 deletions dgraph/cmd/alpha/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"crypto/tls"
"errors"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
Expand Down Expand Up @@ -135,12 +134,6 @@ they form a Raft group and provide synchronous replication.
"If set, all Alter requests to Dgraph would need to have this token."+
" The token can be passed as follows: For HTTP requests, in X-Dgraph-AuthToken header."+
" For Grpc, in auth-token key in the context.")
flag.String("hmac_secret_file", "", "The file storing the HMAC secret"+
" that is used for signing the JWT. Enterprise feature.")
flag.Duration("access_jwt_ttl", 6*time.Hour, "The TTL for the access jwt. "+
"Enterprise feature.")
flag.Duration("refresh_jwt_ttl", 30*24*time.Hour, "The TTL for the refresh jwt. "+
"Enterprise feature.")
flag.Float64P("lru_mb", "l", -1,
"Estimated memory the LRU cache can take. "+
"Actual usage by the process would be more than specified here.")
Expand Down Expand Up @@ -418,20 +411,6 @@ func run() {
AllottedMemory: Alpha.Conf.GetFloat64("lru_mb"),
}

secretFile := Alpha.Conf.GetString("hmac_secret_file")
if secretFile != "" {
hmacSecret, err := ioutil.ReadFile(secretFile)
if err != nil {
glog.Fatalf("Unable to read HMAC secret from file: %v", secretFile)
}

opts.HmacSecret = hmacSecret
opts.AccessJwtTtl = Alpha.Conf.GetDuration("access_jwt_ttl")
opts.RefreshJwtTtl = Alpha.Conf.GetDuration("refresh_jwt_ttl")

glog.Info("HMAC secret loaded successfully.")
}

switch strings.ToLower(Alpha.Conf.GetString("mutations")) {
case "allow":
opts.MutationsMode = edgraph.AllowMutations
Expand Down
7 changes: 1 addition & 6 deletions dgraph/cmd/alpha/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import (
"github.com/dgraph-io/dgraph/protos/pb"
"github.com/dgraph-io/dgraph/query"
"github.com/dgraph-io/dgraph/schema"
"github.com/dgraph-io/dgraph/x"

"github.com/stretchr/testify/require"

Expand Down Expand Up @@ -284,7 +283,6 @@ func TestDeletePredicate(t *testing.T) {
require.JSONEq(t, `{"data":{"schema":[`+
`{"predicate":"_predicate_","type":"string","list":true},`+
`{"predicate":"age","type":"default"},`+
x.AclPredsJson+","+
`{"predicate":"name","type":"string","index":true, "tokenizer":["term"]}`+
`]}}`, output)

Expand Down Expand Up @@ -1291,7 +1289,6 @@ func TestListTypeSchemaChange(t *testing.T) {
require.NoError(t, err)
require.JSONEq(t, `{"data":{"schema":[`+
`{"predicate":"_predicate_","type":"string","list":true},`+
x.AclPredsJson+","+
`{"predicate":"occupations","type":"string"}]}}`, res)

}
Expand Down Expand Up @@ -1383,9 +1380,7 @@ func TestDropAll(t *testing.T) {
output, err = runQuery(q3)
require.NoError(t, err)
require.JSONEq(t,
`{"data":{"schema":[{"predicate":"_predicate_","type":"string","list":true},`+
x.AclPredsJson+
`]}}`, output)
`{"data":{"schema":[{"predicate":"_predicate_","type":"string","list":true}]}}`, output)

// Reinstate schema so that we can re-run the original query.
err = alterSchemaWithRetry(s)
Expand Down
2 changes: 0 additions & 2 deletions dgraph/cmd/root_ee.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,12 @@
package cmd

import (
acl "github.com/dgraph-io/dgraph/ee/acl"
"github.com/dgraph-io/dgraph/ee/backup"
)

func init() {
// subcommands already has the default subcommands, we append to EE ones to that.
subcommands = append(subcommands,
&backup.Restore,
&acl.CmdAcl,
)
}
218 changes: 3 additions & 215 deletions edgraph/access_ee.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,227 +14,15 @@ package edgraph

import (
"context"
"encoding/json"
"fmt"
"strconv"
"time"

"github.com/dgraph-io/dgo/protos/api"
"github.com/dgraph-io/dgraph/ee/acl"
"github.com/dgrijalva/jwt-go"
"github.com/dgraph-io/dgraph/x"
"github.com/golang/glog"
"google.golang.org/grpc/peer"

otrace "go.opencensus.io/trace"
)

func (s *Server) Login(ctx context.Context,
request *api.LoginRequest) (*api.Response, error) {
ctx, span := otrace.StartSpan(ctx, "server.Login")
defer span.End()

// record the client ip for this login request
var addr string
if ip, ok := peer.FromContext(ctx); ok {
addr = ip.Addr.String()
glog.Infof("Login request from: %s", addr)
span.Annotate([]otrace.Attribute{
otrace.StringAttribute("client_ip", addr),
}, "client ip for login")
}

user, err := s.authenticate(ctx, request)
if err != nil {
errMsg := fmt.Sprintf("Authentication from address %s failed: %v", addr, err)
glog.Errorf(errMsg)
return nil, fmt.Errorf(errMsg)
}

resp := &api.Response{}
accessJwt, err := getAccessJwt(request.Userid, user.Groups)
if err != nil {
errMsg := fmt.Sprintf("Unable to get access jwt (userid=%s,addr=%s):%v",
request.Userid, addr, err)
glog.Errorf(errMsg)
return nil, fmt.Errorf(errMsg)
}
refreshJwt, err := getRefreshJwt(request.Userid)
if err != nil {
errMsg := fmt.Sprintf("Unable to get refresh jwt (userid=%s,addr=%s):%v",
request.Userid, addr, err)
glog.Errorf(errMsg)
return nil, fmt.Errorf(errMsg)
}

loginJwt := api.Jwt{
AccessJwt: accessJwt,
RefreshJwt: refreshJwt,
}

jwtBytes, err := loginJwt.Marshal()
if err != nil {
errMsg := fmt.Sprintf("Unable to marshal jwt (userid=%s,addr=%s):%v",
request.Userid, addr, err)
glog.Errorf(errMsg)
return nil, fmt.Errorf(errMsg)
}
resp.Json = jwtBytes
return resp, nil
}

func (s *Server) authenticate(ctx context.Context, request *api.LoginRequest) (*acl.User, error) {
if err := validateLoginRequest(request); err != nil {
return nil, fmt.Errorf("Invalid login request: %v", err)
}

var user *acl.User
if len(request.RefreshToken) > 0 {
userId, err := authenticateRefreshToken(request.RefreshToken)
if err != nil {
return nil, fmt.Errorf("Unable to authenticate the refresh token %v: %v",
request.RefreshToken, err)
}

user, err = s.queryUser(ctx, userId, "")
if err != nil {
return nil, fmt.Errorf("Error while querying user with id: %v",
request.Userid)
}

if user == nil {
return nil, fmt.Errorf("User not found for id %v", request.Userid)
}
} else {
var err error
user, err = s.queryUser(ctx, request.Userid, request.Password)
if err != nil {
return nil, fmt.Errorf("Error while querying user with id: %v",
request.Userid)
}

if user == nil {
return nil, fmt.Errorf("User not found for id %v", request.Userid)
}
if !user.PasswordMatch {
return nil, fmt.Errorf("Password mismatch for user: %v", request.Userid)
}
}

return user, nil
}

func authenticateRefreshToken(refreshToken string) (string, error) {
token, err := jwt.Parse(refreshToken, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return Config.HmacSecret, nil
})

if err != nil {
return "", fmt.Errorf("Unable to parse refresh token:%v", err)
}

claims, ok := token.Claims.(jwt.MapClaims)
if !ok || !token.Valid {
return "", fmt.Errorf("Claims in refresh token is not map claims:%v", refreshToken)
}

// by default, the MapClaims.Valid will return true if the exp field is not set
// here we enforce the checking to make sure that the refresh token has not expired
now := time.Now().Unix()
if !claims.VerifyExpiresAt(now, true) {
return "", fmt.Errorf("Refresh token has expired: %v", refreshToken)
}

userId, ok := claims["userid"].(string)
if !ok {
return "", fmt.Errorf("User ID in claims is not a string:%v", userId)
}
return userId, nil
}

func validateLoginRequest(request *api.LoginRequest) error {
if request == nil {
return fmt.Errorf("The request should not be nil")
}
// we will use the refresh token for authentication if it's set
if len(request.RefreshToken) > 0 {
return nil
}

// otherwise make sure both userid and password are set
if len(request.Userid) == 0 {
return fmt.Errorf("The userid should not be empty")
}
if len(request.Password) == 0 {
return fmt.Errorf("The password should not be empty")
}
return nil
}

func getAccessJwt(userId string, groups []acl.Group) (string, error) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"userid": userId,
"groups": acl.GetGroupIDs(groups),
// set the jwt exp according to the ttl
"exp": json.Number(
strconv.FormatInt(time.Now().Add(Config.AccessJwtTtl).Unix(), 10)),
})

jwtString, err := token.SignedString(Config.HmacSecret)
if err != nil {
return "", fmt.Errorf("Unable to encode jwt to string: %v", err)
}
return jwtString, nil
}

func getRefreshJwt(userId string) (string, error) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"userid": userId,
// set the jwt exp according to the ttl
"exp": json.Number(
strconv.FormatInt(time.Now().Add(Config.RefreshJwtTtl).Unix(), 10)),
})

jwtString, err := token.SignedString(Config.HmacSecret)
if err != nil {
return "", fmt.Errorf("Unable to encode jwt to string: %v", err)
}
return jwtString, nil
}

const queryUser = `
query search($userid: string, $password: string){
user(func: eq(dgraph.xid, $userid)) {
uid
password_match: checkpwd(dgraph.password, $password)
dgraph.user.group {
uid
dgraph.xid
}
}
}`

func (s *Server) queryUser(ctx context.Context, userid string, password string) (user *acl.User,
err error) {
queryVars := map[string]string{
"$userid": userid,
"$password": password,
}
queryRequest := api.Request{
Query: queryUser,
Vars: queryVars,
}

queryResp, err := s.Query(ctx, &queryRequest)
if err != nil {
glog.Errorf("Error while query user with id %s: %v", userid, err)
return nil, err
}
user, err = acl.UnmarshalUser(queryResp, "user")
if err != nil {
return nil, err
}
return user, nil
glog.Warningf("Login failed in version 1.0: %s", x.ErrNotSupported)
return &api.Response{}, x.ErrNotSupported
}
5 changes: 0 additions & 5 deletions edgraph/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package edgraph

import (
"path/filepath"
"time"

"github.com/dgraph-io/dgraph/posting"
"github.com/dgraph-io/dgraph/x"
Expand All @@ -39,10 +38,6 @@ type Options struct {
AuthToken string

AllottedMemory float64

HmacSecret []byte
AccessJwtTtl time.Duration
RefreshJwtTtl time.Duration
}

var Config Options
Expand Down
Loading

0 comments on commit 1b98d81

Please sign in to comment.