From b5bd1aadc960379d1e25d9051ac9da16e4e0b122 Mon Sep 17 00:00:00 2001 From: Abhimanyu Singh Gaur <12651351+abhimanyusinghgaur@users.noreply.github.com> Date: Fri, 3 Jul 2020 16:43:46 +0530 Subject: [PATCH 1/5] feat(Enterprise): GraphQL schema get/update, Dgraph schema query/alter and /login are now admin operations (#5786) Fixes #GRAPHQL-494. Please refer this discuss post: https://discuss.dgraph.io/t/authentication-for-admin-endpoints/6786 (cherry picked from commit 30fb6250fa178a5cc9c4b7d518598188d486f136) # Conflicts: # dgraph/cmd/alpha/mutations_mode/docker-compose.yml # systest/bgindex/docker-compose.yml --- dgraph/cmd/alpha/http.go | 2 + dgraph/cmd/alpha/login_ee.go | 16 +- .../alpha/mutations_mode/docker-compose.yml | 9 +- dgraph/cmd/bulk/systest/docker-compose.yml | 2 +- edgraph/access.go | 6 + edgraph/access_ee.go | 80 ++++++++- edgraph/server.go | 23 ++- ee/acl/acl_test.go | 168 ++++++++++++++++++ graphql/admin/admin.go | 22 ++- graphql/resolve/middlewares.go | 15 +- systest/bgindex/docker-compose.yml | 36 ++-- systest/group-delete/docker-compose.yml | 3 + tlstest/acl/docker-compose.yml | 4 +- tlstest/certrequest/docker-compose.yml | 4 +- tlstest/certverifyifgiven/docker-compose.yml | 4 +- x/x.go | 21 ++- 16 files changed, 337 insertions(+), 78 deletions(-) diff --git a/dgraph/cmd/alpha/http.go b/dgraph/cmd/alpha/http.go index 1419be98eb1..2e64e6f14de 100644 --- a/dgraph/cmd/alpha/http.go +++ b/dgraph/cmd/alpha/http.go @@ -196,6 +196,7 @@ func queryHandler(w http.ResponseWriter, r *http.Request) { ctx := context.WithValue(r.Context(), query.DebugKey, isDebugMode) ctx = x.AttachAccessJwt(ctx, r) + ctx = x.AttachRemoteIP(ctx, r) if queryTimeout != 0 { var cancel context.CancelFunc @@ -568,6 +569,7 @@ func alterHandler(w http.ResponseWriter, r *http.Request) { md.Append("auth-token", r.Header.Get("X-Dgraph-AuthToken")) ctx := metadata.NewIncomingContext(context.Background(), md) ctx = x.AttachAccessJwt(ctx, r) + ctx = x.AttachRemoteIP(ctx, r) if _, err := (&edgraph.Server{}).Alter(ctx, op); err != nil { x.SetStatus(w, x.Error, err.Error()) return diff --git a/dgraph/cmd/alpha/login_ee.go b/dgraph/cmd/alpha/login_ee.go index c73608331b6..ee205fd82cf 100644 --- a/dgraph/cmd/alpha/login_ee.go +++ b/dgraph/cmd/alpha/login_ee.go @@ -21,15 +21,12 @@ package alpha import ( "context" "encoding/json" - "net" "net/http" - "strconv" "github.com/dgraph-io/dgo/v200/protos/api" "github.com/dgraph-io/dgraph/edgraph" "github.com/dgraph-io/dgraph/x" "github.com/golang/glog" - "google.golang.org/grpc/peer" ) func loginHandler(w http.ResponseWriter, r *http.Request) { @@ -37,18 +34,7 @@ func loginHandler(w http.ResponseWriter, r *http.Request) { return } - ctx := context.Background() - if ip, port, err := net.SplitHostPort(r.RemoteAddr); err == nil { - // add remote addr as peer info so that the remote address can be logged inside Server.Login - if intPort, convErr := strconv.Atoi(port); convErr == nil { - ctx = peer.NewContext(ctx, &peer.Peer{ - Addr: &net.TCPAddr{ - IP: net.ParseIP(ip), - Port: intPort, - }, - }) - } - } + ctx := x.AttachRemoteIP(context.Background(), r) body := readRequest(w, r) loginReq := api.LoginRequest{} diff --git a/dgraph/cmd/alpha/mutations_mode/docker-compose.yml b/dgraph/cmd/alpha/mutations_mode/docker-compose.yml index 32c0411e039..be744ef459d 100644 --- a/dgraph/cmd/alpha/mutations_mode/docker-compose.yml +++ b/dgraph/cmd/alpha/mutations_mode/docker-compose.yml @@ -65,7 +65,8 @@ services: - 9180:9180 labels: cluster: test - command: /gobin/dgraph alpha --my=dg1:7180 --lru_mb=1024 --zero=zero1:5180 -o 100 --logtostderr --mutations=disallow + command: /gobin/dgraph alpha --my=dg1:7180 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 + -o 100 --logtostderr --mutations=disallow --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 dg2: image: dgraph/dgraph:latest @@ -83,7 +84,8 @@ services: - 9182:9182 labels: cluster: test - command: /gobin/dgraph alpha --my=dg2:7182 --lru_mb=1024 --zero=zero1:5180 -o 102 --logtostderr --mutations=strict + command: /gobin/dgraph alpha --my=dg2:7182 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 + -o 100 --logtostderr --mutations=strict --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 dg3: image: dgraph/dgraph:latest @@ -101,4 +103,5 @@ services: - 9183:9183 labels: cluster: test - command: /gobin/dgraph alpha --my=dg3:7183 --lru_mb=1024 --zero=zero1:5180 -o 103 --logtostderr --mutations=strict + command: /gobin/dgraph alpha --my=dg3:7183 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 + -o 103 --logtostderr --mutations=strict --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 diff --git a/dgraph/cmd/bulk/systest/docker-compose.yml b/dgraph/cmd/bulk/systest/docker-compose.yml index 50f1b3b17a8..26d61e69948 100644 --- a/dgraph/cmd/bulk/systest/docker-compose.yml +++ b/dgraph/cmd/bulk/systest/docker-compose.yml @@ -17,7 +17,7 @@ services: target: /gobin read_only: true command: /gobin/dgraph alpha -o 100 --my=alpha1:7180 --lru_mb=1024 --zero=zero1:5180 - --logtostderr -v=2 --idx=1 + --logtostderr -v=2 --idx=1 --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 zero1: image: dgraph/dgraph:latest container_name: zero1 diff --git a/edgraph/access.go b/edgraph/access.go index d8ffc434db3..c79873105fc 100644 --- a/edgraph/access.go +++ b/edgraph/access.go @@ -24,6 +24,7 @@ import ( "github.com/dgraph-io/badger/v2/y" "github.com/dgraph-io/dgo/v200/protos/api" "github.com/dgraph-io/dgraph/gql" + "github.com/dgraph-io/dgraph/query" "github.com/dgraph-io/dgraph/x" "github.com/golang/glog" ) @@ -65,6 +66,11 @@ func authorizeQuery(ctx context.Context, parsedReq *gql.Result, graphql bool) er return nil } +func authorizeSchemaQuery(ctx context.Context, er *query.ExecutionResult) error { + // always allow schema access + return nil +} + func AuthorizeGuardians(ctx context.Context) error { // always allow access return nil diff --git a/edgraph/access_ee.go b/edgraph/access_ee.go index 04d1e306f9d..852bfd01b0d 100644 --- a/edgraph/access_ee.go +++ b/edgraph/access_ee.go @@ -19,6 +19,10 @@ import ( "strings" "time" + "github.com/dgraph-io/dgraph/protos/pb" + + "github.com/dgraph-io/dgraph/query" + "github.com/pkg/errors" "github.com/dgraph-io/badger/v2/y" @@ -33,7 +37,6 @@ import ( "github.com/golang/glog" otrace "go.opencensus.io/trace" "google.golang.org/grpc/codes" - "google.golang.org/grpc/peer" "google.golang.org/grpc/status" ) @@ -55,9 +58,10 @@ func (s *Server) Login(ctx context.Context, // record the client ip for this login request var addr string - if peerInfo, ok := peer.FromContext(ctx); ok { - addr = peerInfo.Addr.String() - glog.Infof("Login request from: %s", addr) + if ipAddr, err := hasAdminAuth(ctx, "Login"); err != nil { + return nil, err + } else { + addr = ipAddr.String() span.Annotate([]otrace.Attribute{ otrace.StringAttribute("client_ip", addr), }, "client ip for login") @@ -794,6 +798,74 @@ func authorizeQuery(ctx context.Context, parsedReq *gql.Result, graphql bool) er return nil } +func authorizeSchemaQuery(ctx context.Context, er *query.ExecutionResult) error { + if len(worker.Config.HmacSecret) == 0 { + // the user has not turned on the acl feature + return nil + } + + // find the predicates being sent in response + preds := make([]string, 0) + predsMap := make(map[string]struct{}) + for _, predNode := range er.SchemaNode { + preds = append(preds, predNode.Predicate) + predsMap[predNode.Predicate] = struct{}{} + } + for _, typeNode := range er.Types { + for _, field := range typeNode.Fields { + if _, ok := predsMap[field.Predicate]; !ok { + preds = append(preds, field.Predicate) + } + } + } + + doAuthorizeSchemaQuery := func() (map[string]struct{}, error) { + userData, err := extractUserAndGroups(ctx) + if err != nil { + return nil, status.Error(codes.Unauthenticated, err.Error()) + } + + userId := userData[0] + groupIds := userData[1:] + + if x.IsGuardian(groupIds) { + // Members of guardian groups are allowed to query anything. + return nil, nil + } + + return authorizePreds(userId, groupIds, preds, acl.Read), nil + } + + // find the predicates which are blocked for the schema query + blockedPreds, err := doAuthorizeSchemaQuery() + if err != nil { + return err + } + + // remove those predicates from response + if len(blockedPreds) > 0 { + respPreds := make([]*pb.SchemaNode, 0) + for _, predNode := range er.SchemaNode { + if _, ok := blockedPreds[predNode.Predicate]; !ok { + respPreds = append(respPreds, predNode) + } + } + er.SchemaNode = respPreds + + for _, typeNode := range er.Types { + respFields := make([]*pb.SchemaUpdate, 0) + for _, field := range typeNode.Fields { + if _, ok := blockedPreds[field.Predicate]; !ok { + respFields = append(respFields, field) + } + } + typeNode.Fields = respFields + } + } + + return nil +} + // AuthorizeGuardians authorizes the operation for users which belong to Guardians group. func AuthorizeGuardians(ctx context.Context) error { if len(worker.Config.HmacSecret) == 0 { diff --git a/edgraph/server.go b/edgraph/server.go index 15c6b930dc9..39ec7919601 100644 --- a/edgraph/server.go +++ b/edgraph/server.go @@ -21,6 +21,7 @@ import ( "context" "encoding/json" "math" + "net" "sort" "strconv" "strings" @@ -37,7 +38,6 @@ import ( otrace "go.opencensus.io/trace" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" - "google.golang.org/grpc/peer" "google.golang.org/grpc/status" "github.com/dgraph-io/dgo/v200" @@ -154,7 +154,7 @@ func (s *Server) Alter(ctx context.Context, op *api.Operation) (*api.Payload, er if !isMutationAllowed(ctx) { return nil, errors.Errorf("No mutations allowed by server.") } - if err := isAlterAllowed(ctx); err != nil { + if _, err := hasAdminAuth(ctx, "Alter"); err != nil { glog.Warningf("Alter denied with error: %v\n", err) return nil, err } @@ -953,6 +953,9 @@ func processQuery(ctx context.Context, qc *queryContext) (*api.Response, error) } if len(er.SchemaNode) > 0 || len(er.Types) > 0 { + if err = authorizeSchemaQuery(ctx, &er); err != nil { + return resp, err + } sort.Slice(er.SchemaNode, func(i, j int) bool { return er.SchemaNode[i].Predicate < er.SchemaNode[j].Predicate }) @@ -1155,11 +1158,19 @@ func isMutationAllowed(ctx context.Context) bool { var errNoAuth = errors.Errorf("No Auth Token found. Token needed for Alter operations.") -func isAlterAllowed(ctx context.Context) error { - p, ok := peer.FromContext(ctx) - if ok { - glog.Infof("Got Alter request from %q\n", p.Addr) +func hasAdminAuth(ctx context.Context, tag string) (net.Addr, error) { + ipAddr, err := x.HasWhitelistedIP(ctx) + if err != nil { + return nil, err } + glog.Infof("Got %s request from: %q\n", tag, ipAddr) + if err = hasPoormansAuth(ctx); err != nil { + return nil, err + } + return ipAddr, nil +} + +func hasPoormansAuth(ctx context.Context) error { if len(worker.Config.AuthToken) == 0 { return nil } diff --git a/ee/acl/acl_test.go b/ee/acl/acl_test.go index c27cd5f0475..d56b257b959 100644 --- a/ee/acl/acl_test.go +++ b/ee/acl/acl_test.go @@ -1582,6 +1582,174 @@ func TestQueriesForNonGuardianUserWithoutGroup(t *testing.T) { testutil.CompareJSON(t, `{"queryUser": [{ "groups": [], "name": "alice"}]}`, string(resp.Data)) } +func TestSchemaQueryWithACL(t *testing.T) { + schemaQuery := "schema{}" + grootSchema := `{ + "schema": [ + { + "predicate": "dgraph.acl.rule", + "type": "uid", + "list": true + }, + { + "predicate": "dgraph.graphql.schema", + "type": "string" + }, + { + "predicate": "dgraph.graphql.xid", + "type": "string", + "index": true, + "tokenizer": [ + "exact" + ], + "upsert": true + }, + { + "predicate": "dgraph.password", + "type": "password" + }, + { + "predicate": "dgraph.rule.permission", + "type": "int" + }, + { + "predicate": "dgraph.rule.predicate", + "type": "string", + "index": true, + "tokenizer": [ + "exact" + ], + "upsert": true + }, + { + "predicate": "dgraph.type", + "type": "string", + "index": true, + "tokenizer": [ + "exact" + ], + "list": true + }, + { + "predicate": "dgraph.user.group", + "type": "uid", + "reverse": true, + "list": true + }, + { + "predicate": "dgraph.xid", + "type": "string", + "index": true, + "tokenizer": [ + "exact" + ], + "upsert": true + } + ], + "types": [ + { + "fields": [ + { + "name": "dgraph.graphql.schema" + }, + { + "name": "dgraph.graphql.xid" + } + ], + "name": "dgraph.graphql" + }, + { + "fields": [ + { + "name": "dgraph.xid" + }, + { + "name": "dgraph.acl.rule" + } + ], + "name": "dgraph.type.Group" + }, + { + "fields": [ + { + "name": "dgraph.rule.predicate" + }, + { + "name": "dgraph.rule.permission" + } + ], + "name": "dgraph.type.Rule" + }, + { + "fields": [ + { + "name": "dgraph.xid" + }, + { + "name": "dgraph.password" + }, + { + "name": "dgraph.user.group" + } + ], + "name": "dgraph.type.User" + } + ] +}` + aliceSchema := `{ + "schema": [ + { + "predicate": "name", + "type": "string", + "index": true, + "tokenizer": [ + "exact" + ] + } + ], + "types": [ + { + "fields": [], + "name": "dgraph.graphql" + }, + { + "fields": [], + "name": "dgraph.type.Group" + }, + { + "fields": [], + "name": "dgraph.type.Rule" + }, + { + "fields": [], + "name": "dgraph.type.User" + } + ] +}` + + // guardian user should be able to view full schema + dg, err := testutil.DgraphClientWithGroot(testutil.SockAddr) + require.NoError(t, err) + testutil.DropAll(t, dg) + resp, err := dg.NewReadOnlyTxn().Query(context.Background(), schemaQuery) + require.NoError(t, err) + require.JSONEq(t, grootSchema, string(resp.GetJson())) + + // add another user and some data for that user with permissions on predicates + resetUser(t) + ctx, _ := context.WithTimeout(context.Background(), 100*time.Second) + addDataAndRules(ctx, t, dg) + time.Sleep(6 * time.Second) // wait for ACL cache to refresh, otherwise it will be flaky test + + // the other user should be able to view only the part of schema for which it has read access + dg, err = testutil.DgraphClient(testutil.SockAddr) + require.NoError(t, err) + require.NoError(t, dg.Login(context.Background(), userid, userpassword)) + resp, err = dg.NewReadOnlyTxn().Query(context.Background(), schemaQuery) + require.NoError(t, err) + require.JSONEq(t, aliceSchema, string(resp.GetJson())) +} + func TestDeleteUserShouldDeleteUserFromGroup(t *testing.T) { resetUser(t) diff --git a/graphql/admin/admin.go b/graphql/admin/admin.go index cdf7b427042..394faecaa14 100644 --- a/graphql/admin/admin.go +++ b/graphql/admin/admin.go @@ -300,13 +300,12 @@ var ( resolve.GuardianAuthMW4Mutation, } adminQueryMWConfig = map[string]resolve.QueryMiddlewares{ - "health": {resolve.IpWhitelistingMW4Query}, // dgraph handles Guardian auth for health + "health": {resolve.IpWhitelistingMW4Query}, // dgraph checks Guardian auth for health "state": {resolve.IpWhitelistingMW4Query}, // dgraph handles Guardian auth for state "config": commonAdminQueryMWs, "listBackups": commonAdminQueryMWs, "restoreStatus": commonAdminQueryMWs, - // not applying ip whitelisting to keep it in sync with /alter - "getGQLSchema": {resolve.GuardianAuthMW4Query}, + "getGQLSchema": commonAdminQueryMWs, // for queries and mutations related to User/Group, dgraph handles Guardian auth, // so no need to apply GuardianAuth Middleware "queryGroup": {resolve.IpWhitelistingMW4Query}, @@ -316,15 +315,14 @@ var ( "getUser": {resolve.IpWhitelistingMW4Query}, } adminMutationMWConfig = map[string]resolve.MutationMiddlewares{ - "backup": commonAdminMutationMWs, - "config": commonAdminMutationMWs, - "draining": commonAdminMutationMWs, - "export": commonAdminMutationMWs, - "login": {resolve.IpWhitelistingMW4Mutation}, - "restore": commonAdminMutationMWs, - "shutdown": commonAdminMutationMWs, - // not applying ip whitelisting to keep it in sync with /alter - "updateGQLSchema": {resolve.GuardianAuthMW4Mutation}, + "backup": commonAdminMutationMWs, + "config": commonAdminMutationMWs, + "draining": commonAdminMutationMWs, + "export": commonAdminMutationMWs, + "login": {resolve.IpWhitelistingMW4Mutation}, + "restore": commonAdminMutationMWs, + "shutdown": commonAdminMutationMWs, + "updateGQLSchema": commonAdminMutationMWs, // for queries and mutations related to User/Group, dgraph handles Guardian auth, // so no need to apply GuardianAuth Middleware "addUser": {resolve.IpWhitelistingMW4Mutation}, diff --git a/graphql/resolve/middlewares.go b/graphql/resolve/middlewares.go index 82af2112a1d..f6fe50f7573 100644 --- a/graphql/resolve/middlewares.go +++ b/graphql/resolve/middlewares.go @@ -18,11 +18,6 @@ package resolve import ( "context" - "net" - - "github.com/pkg/errors" - - "google.golang.org/grpc/peer" "github.com/dgraph-io/dgraph/edgraph" "github.com/dgraph-io/dgraph/graphql/schema" @@ -122,17 +117,9 @@ func resolveGuardianAuth(ctx context.Context, f schema.Field) *Resolved { } func resolveIpWhitelisting(ctx context.Context, f schema.Field) *Resolved { - peerInfo, ok := peer.FromContext(ctx) - if !ok { - return EmptyResult(f, errors.New("unable to find source ip")) - } - ip, _, err := net.SplitHostPort(peerInfo.Addr.String()) - if err != nil { + if _, err := x.HasWhitelistedIP(ctx); err != nil { return EmptyResult(f, err) } - if !x.IsIpWhitelisted(ip) { - return EmptyResult(f, errors.Errorf("unauthorized ip address: %s", ip)) - } return nil } diff --git a/systest/bgindex/docker-compose.yml b/systest/bgindex/docker-compose.yml index dad68cdba79..0261aab9ae0 100644 --- a/systest/bgindex/docker-compose.yml +++ b/systest/bgindex/docker-compose.yml @@ -20,9 +20,9 @@ services: source: ../../ee/acl/hmac-secret target: /secret/hmac read_only: true - command: /gobin/dgraph alpha -o 100 --my=alpha1:7180 --lru_mb=1024 --zero=zero1:5180 - --logtostderr -v=2 --idx=1 --acl_secret_file=/secret/hmac --acl_access_ttl 300s - --acl_cache_ttl 500s + command: /gobin/dgraph alpha -o 100 --my=alpha1:7180 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 + --logtostderr -v=2 --idx=1 --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 + --acl_secret_file=/secret/hmac --acl_access_ttl 300s --acl_cache_ttl 500s alpha2: image: dgraph/dgraph:latest container_name: alpha2 @@ -43,9 +43,9 @@ services: source: ../../ee/acl/hmac-secret target: /secret/hmac read_only: true - command: /gobin/dgraph alpha -o 102 --my=alpha2:7182 --lru_mb=1024 --zero=zero1:5180 - --logtostderr -v=2 --idx=2 --acl_secret_file=/secret/hmac --acl_access_ttl 300s - --acl_cache_ttl 500s + command: /gobin/dgraph alpha -o 102 --my=alpha2:7182 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 + --logtostderr -v=2 --idx=2 --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 + --acl_secret_file=/secret/hmac --acl_access_ttl 300s --acl_cache_ttl 500s alpha3: image: dgraph/dgraph:latest container_name: alpha3 @@ -66,9 +66,9 @@ services: source: ../../ee/acl/hmac-secret target: /secret/hmac read_only: true - command: /gobin/dgraph alpha -o 103 --my=alpha3:7183 --lru_mb=1024 --zero=zero1:5180 - --logtostderr -v=2 --idx=3 --acl_secret_file=/secret/hmac --acl_access_ttl 300s - --acl_cache_ttl 500s + command: /gobin/dgraph alpha -o 103 --my=alpha3:7183 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 + --logtostderr -v=2 --idx=3 --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 + --acl_secret_file=/secret/hmac --acl_access_ttl 300s --acl_cache_ttl 500s alpha4: image: dgraph/dgraph:latest container_name: alpha4 @@ -89,9 +89,9 @@ services: source: ../../ee/acl/hmac-secret target: /secret/hmac read_only: true - command: /gobin/dgraph alpha -o 104 --my=alpha4:7184 --lru_mb=1024 --zero=zero1:5180 - --logtostderr -v=2 --idx=4 --acl_secret_file=/secret/hmac --acl_access_ttl 300s - --acl_cache_ttl 500s + command: /gobin/dgraph alpha -o 104 --my=alpha4:7184 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 + --logtostderr -v=2 --idx=4 --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 + --acl_secret_file=/secret/hmac --acl_access_ttl 300s --acl_cache_ttl 500s alpha5: image: dgraph/dgraph:latest container_name: alpha5 @@ -112,9 +112,9 @@ services: source: ../../ee/acl/hmac-secret target: /secret/hmac read_only: true - command: /gobin/dgraph alpha -o 105 --my=alpha5:7185 --lru_mb=1024 --zero=zero1:5180 - --logtostderr -v=2 --idx=5 --acl_secret_file=/secret/hmac --acl_access_ttl 300s - --acl_cache_ttl 500s + command: /gobin/dgraph alpha -o 105 --my=alpha5:7185 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 + --logtostderr -v=2 --idx=5 --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 + --acl_secret_file=/secret/hmac --acl_access_ttl 300s --acl_cache_ttl 500s alpha6: image: dgraph/dgraph:latest container_name: alpha6 @@ -135,9 +135,9 @@ services: source: ../../ee/acl/hmac-secret target: /secret/hmac read_only: true - command: /gobin/dgraph alpha -o 106 --my=alpha6:7186 --lru_mb=1024 --zero=zero1:5180 - --logtostderr -v=2 --idx=6 --acl_secret_file=/secret/hmac --acl_access_ttl 300s - --acl_cache_ttl 500s + command: /gobin/dgraph alpha -o 106 --my=alpha6:7186 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 + --logtostderr -v=2 --idx=6 --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 + --acl_secret_file=/secret/hmac --acl_access_ttl 300s --acl_cache_ttl 500s zero1: image: dgraph/dgraph:latest container_name: zero1 diff --git a/systest/group-delete/docker-compose.yml b/systest/group-delete/docker-compose.yml index a9c60f4f303..cacb2514fd3 100644 --- a/systest/group-delete/docker-compose.yml +++ b/systest/group-delete/docker-compose.yml @@ -32,6 +32,7 @@ services: labels: cluster: test command: /gobin/dgraph alpha --my=dg1:7180 --lru_mb=1024 --zero=zero1:5180 -o 100 --logtostderr + --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 dg2: image: dgraph/dgraph:latest @@ -50,6 +51,7 @@ services: labels: cluster: test command: /gobin/dgraph alpha --my=dg2:7182 --lru_mb=1024 --zero=zero1:5180 -o 102 --logtostderr + --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 dg3: image: dgraph/dgraph:latest @@ -68,3 +70,4 @@ services: labels: cluster: test command: /gobin/dgraph alpha --my=dg3:7183 --lru_mb=1024 --zero=zero1:5180 -o 103 --logtostderr + --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 diff --git a/tlstest/acl/docker-compose.yml b/tlstest/acl/docker-compose.yml index 3e00438829b..8e28107eabd 100644 --- a/tlstest/acl/docker-compose.yml +++ b/tlstest/acl/docker-compose.yml @@ -22,7 +22,9 @@ services: source: ../tls target: /dgraph-tls read_only: true - command: /gobin/dgraph alpha -o 100 --my=alpha1:7180 --lru_mb=1024 --zero=zero1:5180 --logtostderr -v=2 --tls_dir /dgraph-tls --tls_client_auth VERIFYIFGIVEN --acl_secret_file /dgraph-acl/hmac-secret + command: /gobin/dgraph alpha -o 100 --my=alpha1:7180 --lru_mb=1024 --zero=zero1:5180 + --logtostderr -v=2 --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 --tls_dir /dgraph-tls + --tls_client_auth VERIFYIFGIVEN --acl_secret_file /dgraph-acl/hmac-secret zero1: image: dgraph/dgraph:latest container_name: zero1 diff --git a/tlstest/certrequest/docker-compose.yml b/tlstest/certrequest/docker-compose.yml index 75ce0ceb7fb..b8fa527be0e 100644 --- a/tlstest/certrequest/docker-compose.yml +++ b/tlstest/certrequest/docker-compose.yml @@ -18,7 +18,9 @@ services: source: ../tls target: /dgraph-tls read_only: true - command: /gobin/dgraph alpha -o 100 --my=alpha1:7180 --lru_mb=1024 --zero=zero1:5180 --logtostderr -v=2 --tls_dir /dgraph-tls --tls_client_auth REQUEST + command: /gobin/dgraph alpha -o 100 --my=alpha1:7180 --lru_mb=1024 --zero=zero1:5180 + --logtostderr -v=2 --tls_dir /dgraph-tls --tls_client_auth REQUEST + --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 zero1: image: dgraph/dgraph:latest container_name: zero1 diff --git a/tlstest/certverifyifgiven/docker-compose.yml b/tlstest/certverifyifgiven/docker-compose.yml index 88569613554..1c335896daf 100644 --- a/tlstest/certverifyifgiven/docker-compose.yml +++ b/tlstest/certverifyifgiven/docker-compose.yml @@ -18,7 +18,9 @@ services: source: ../tls target: /dgraph-tls read_only: true - command: /gobin/dgraph alpha -o 100 --my=alpha1:7180 --lru_mb=1024 --zero=zero1:5180 --logtostderr -v=2 --tls_dir /dgraph-tls --tls_client_auth VERIFYIFGIVEN + command: /gobin/dgraph alpha -o 100 --my=alpha1:7180 --lru_mb=1024 --zero=zero1:5180 + --logtostderr -v=2 --tls_dir /dgraph-tls --tls_client_auth VERIFYIFGIVEN + --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 zero1: image: dgraph/dgraph:latest container_name: zero1 diff --git a/x/x.go b/x/x.go index 8a1c441af99..1edf76f6f90 100644 --- a/x/x.go +++ b/x/x.go @@ -393,8 +393,8 @@ func AttachRemoteIP(ctx context.Context, r *http.Request) context.Context { return ctx } -// IsIpWhitelisted checks if the given ipString is within the whitelisted ip range -func IsIpWhitelisted(ipString string) bool { +// isIpWhitelisted checks if the given ipString is within the whitelisted ip range +func isIpWhitelisted(ipString string) bool { ip := net.ParseIP(ipString) if ip == nil { @@ -413,6 +413,23 @@ func IsIpWhitelisted(ipString string) bool { return false } +// HasWhitelistedIP checks whether the source IP in ctx is whitelisted or not. +// It returns the IP address if the IP is whitelisted, otherwise an error is returned. +func HasWhitelistedIP(ctx context.Context) (net.Addr, error) { + peerInfo, ok := peer.FromContext(ctx) + if !ok { + return nil, errors.New("unable to find source ip") + } + ip, _, err := net.SplitHostPort(peerInfo.Addr.String()) + if err != nil { + return nil, err + } + if !isIpWhitelisted(ip) { + return nil, errors.Errorf("unauthorized ip address: %s", ip) + } + return peerInfo.Addr, nil +} + // Write response body, transparently compressing if necessary. func WriteResponse(w http.ResponseWriter, r *http.Request, b []byte) (int, error) { var out io.Writer = w From 3263d0b6e507d277098c437d48cf8ce0ee5ec374 Mon Sep 17 00:00:00 2001 From: Abhimanyu Singh Gaur <12651351+abhimanyusinghgaur@users.noreply.github.com> Date: Mon, 6 Jul 2020 21:34:05 +0530 Subject: [PATCH 2/5] remove unnecessary IP attach --- dgraph/cmd/alpha/http.go | 1 - 1 file changed, 1 deletion(-) diff --git a/dgraph/cmd/alpha/http.go b/dgraph/cmd/alpha/http.go index 2e64e6f14de..7725e8503e4 100644 --- a/dgraph/cmd/alpha/http.go +++ b/dgraph/cmd/alpha/http.go @@ -196,7 +196,6 @@ func queryHandler(w http.ResponseWriter, r *http.Request) { ctx := context.WithValue(r.Context(), query.DebugKey, isDebugMode) ctx = x.AttachAccessJwt(ctx, r) - ctx = x.AttachRemoteIP(ctx, r) if queryTimeout != 0 { var cancel context.CancelFunc From d7d8212c52caed79fe3cc024eed11e4b9a58b3c6 Mon Sep 17 00:00:00 2001 From: Abhimanyu Singh Gaur <12651351+abhimanyusinghgaur@users.noreply.github.com> Date: Tue, 7 Jul 2020 10:17:21 +0530 Subject: [PATCH 3/5] fix compose file --- dgraph/cmd/alpha/mutations_mode/docker-compose.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dgraph/cmd/alpha/mutations_mode/docker-compose.yml b/dgraph/cmd/alpha/mutations_mode/docker-compose.yml index be744ef459d..7edf352cd1c 100644 --- a/dgraph/cmd/alpha/mutations_mode/docker-compose.yml +++ b/dgraph/cmd/alpha/mutations_mode/docker-compose.yml @@ -65,8 +65,8 @@ services: - 9180:9180 labels: cluster: test - command: /gobin/dgraph alpha --my=dg1:7180 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 - -o 100 --logtostderr --mutations=disallow --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 + command: /gobin/dgraph alpha --my=dg1:7180 --lru_mb=1024 --zero=zero1:5180 -o 100 + --logtostderr --mutations=disallow --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 dg2: image: dgraph/dgraph:latest @@ -84,8 +84,8 @@ services: - 9182:9182 labels: cluster: test - command: /gobin/dgraph alpha --my=dg2:7182 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 - -o 100 --logtostderr --mutations=strict --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 + command: /gobin/dgraph alpha --my=dg2:7182 --lru_mb=1024 --zero=zero1:5180 -o 102 + --logtostderr --mutations=strict --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 dg3: image: dgraph/dgraph:latest @@ -103,5 +103,5 @@ services: - 9183:9183 labels: cluster: test - command: /gobin/dgraph alpha --my=dg3:7183 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 - -o 103 --logtostderr --mutations=strict --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 + command: /gobin/dgraph alpha --my=dg3:7183 --lru_mb=1024 --zero=zero1:5180 -o 103 + --logtostderr --mutations=strict --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 From 48a606d6440f36f4ab0f60b0d6e62806d0c3cf04 Mon Sep 17 00:00:00 2001 From: Abhimanyu Singh Gaur <12651351+abhimanyusinghgaur@users.noreply.github.com> Date: Tue, 7 Jul 2020 11:02:34 +0530 Subject: [PATCH 4/5] make CI work :( --- systest/bgindex/docker-compose.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/systest/bgindex/docker-compose.yml b/systest/bgindex/docker-compose.yml index 0261aab9ae0..b7eaf992fa1 100644 --- a/systest/bgindex/docker-compose.yml +++ b/systest/bgindex/docker-compose.yml @@ -20,7 +20,7 @@ services: source: ../../ee/acl/hmac-secret target: /secret/hmac read_only: true - command: /gobin/dgraph alpha -o 100 --my=alpha1:7180 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 + command: /gobin/dgraph alpha -o 100 --my=alpha1:7180 --lru_mb=1024 --zero=zero1:5180 --logtostderr -v=2 --idx=1 --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 --acl_secret_file=/secret/hmac --acl_access_ttl 300s --acl_cache_ttl 500s alpha2: @@ -43,7 +43,7 @@ services: source: ../../ee/acl/hmac-secret target: /secret/hmac read_only: true - command: /gobin/dgraph alpha -o 102 --my=alpha2:7182 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 + command: /gobin/dgraph alpha -o 102 --my=alpha2:7182 --lru_mb=1024 --zero=zero1:5180 --logtostderr -v=2 --idx=2 --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 --acl_secret_file=/secret/hmac --acl_access_ttl 300s --acl_cache_ttl 500s alpha3: @@ -66,7 +66,7 @@ services: source: ../../ee/acl/hmac-secret target: /secret/hmac read_only: true - command: /gobin/dgraph alpha -o 103 --my=alpha3:7183 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 + command: /gobin/dgraph alpha -o 103 --my=alpha3:7183 --lru_mb=1024 --zero=zero1:5180 --logtostderr -v=2 --idx=3 --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 --acl_secret_file=/secret/hmac --acl_access_ttl 300s --acl_cache_ttl 500s alpha4: @@ -89,7 +89,7 @@ services: source: ../../ee/acl/hmac-secret target: /secret/hmac read_only: true - command: /gobin/dgraph alpha -o 104 --my=alpha4:7184 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 + command: /gobin/dgraph alpha -o 104 --my=alpha4:7184 --lru_mb=1024 --zero=zero1:5180 --logtostderr -v=2 --idx=4 --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 --acl_secret_file=/secret/hmac --acl_access_ttl 300s --acl_cache_ttl 500s alpha5: @@ -112,7 +112,7 @@ services: source: ../../ee/acl/hmac-secret target: /secret/hmac read_only: true - command: /gobin/dgraph alpha -o 105 --my=alpha5:7185 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 + command: /gobin/dgraph alpha -o 105 --my=alpha5:7185 --lru_mb=1024 --zero=zero1:5180 --logtostderr -v=2 --idx=5 --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 --acl_secret_file=/secret/hmac --acl_access_ttl 300s --acl_cache_ttl 500s alpha6: @@ -135,7 +135,7 @@ services: source: ../../ee/acl/hmac-secret target: /secret/hmac read_only: true - command: /gobin/dgraph alpha -o 106 --my=alpha6:7186 --lru_mb=1024 --zero=zero1:5180,zero2:5182,zero3:5183 + command: /gobin/dgraph alpha -o 106 --my=alpha6:7186 --lru_mb=1024 --zero=zero1:5180 --logtostderr -v=2 --idx=6 --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 --acl_secret_file=/secret/hmac --acl_access_ttl 300s --acl_cache_ttl 500s zero1: From c103d3d6a56841e7d6f1857faf8dc65b905afc6e Mon Sep 17 00:00:00 2001 From: Abhimanyu Singh Gaur <12651351+abhimanyusinghgaur@users.noreply.github.com> Date: Tue, 7 Jul 2020 14:57:41 +0530 Subject: [PATCH 5/5] fix compose file --- dgraph/cmd/alpha/mutations_mode/docker-compose.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dgraph/cmd/alpha/mutations_mode/docker-compose.yml b/dgraph/cmd/alpha/mutations_mode/docker-compose.yml index 7edf352cd1c..e2208978b7c 100644 --- a/dgraph/cmd/alpha/mutations_mode/docker-compose.yml +++ b/dgraph/cmd/alpha/mutations_mode/docker-compose.yml @@ -66,7 +66,7 @@ services: labels: cluster: test command: /gobin/dgraph alpha --my=dg1:7180 --lru_mb=1024 --zero=zero1:5180 -o 100 - --logtostderr --mutations=disallow --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 + --logtostderr --mutations=disallow --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 dg2: image: dgraph/dgraph:latest @@ -85,7 +85,7 @@ services: labels: cluster: test command: /gobin/dgraph alpha --my=dg2:7182 --lru_mb=1024 --zero=zero1:5180 -o 102 - --logtostderr --mutations=strict --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 + --logtostderr --mutations=strict --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 dg3: image: dgraph/dgraph:latest @@ -104,4 +104,4 @@ services: labels: cluster: test command: /gobin/dgraph alpha --my=dg3:7183 --lru_mb=1024 --zero=zero1:5180 -o 103 - --logtostderr --mutations=strict --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 + --logtostderr --mutations=strict --whitelist=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16