Skip to content

Commit 42115e4

Browse files
fix(acl): fix duplicate groot user creation (#9041)
This PR adds the unique directive to the 'dgraph.xid' predicate. Prior to this change, users could create duplicate users leading to misconfiguration of ACL. --------- Co-authored-by: ShivajiKharse <[email protected]> Co-authored-by: shivaji-dgraph <[email protected]>
1 parent 532df27 commit 42115e4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+2099
-818
lines changed

check_upgrade/check_upgrade.go

Lines changed: 591 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
//go:build integration2
2+
3+
/*
4+
* Copyright 2024 Dgraph Labs, Inc. and Contributors
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package checkupgrade
20+
21+
import (
22+
"context"
23+
"fmt"
24+
"os/exec"
25+
"path/filepath"
26+
"regexp"
27+
"testing"
28+
"time"
29+
30+
"github.com/dgraph-io/dgo/v230/protos/api"
31+
"github.com/dgraph-io/dgraph/dgraphapi"
32+
"github.com/dgraph-io/dgraph/dgraphtest"
33+
"github.com/dgraph-io/dgraph/x"
34+
"github.com/golang-jwt/jwt/v5"
35+
"github.com/stretchr/testify/require"
36+
)
37+
38+
func TestCheckUpgrade(t *testing.T) {
39+
conf := dgraphtest.NewClusterConfig().WithNumAlphas(1).WithNumZeros(1).WithReplicas(1).
40+
WithACL(time.Hour).WithVersion("57aa5c4ac")
41+
c, err := dgraphtest.NewLocalCluster(conf)
42+
require.NoError(t, err)
43+
defer func() { c.Cleanup(t.Failed()) }()
44+
require.NoError(t, c.Start())
45+
46+
gc, cleanup, err := c.Client()
47+
require.NoError(t, err)
48+
defer cleanup()
49+
require.NoError(t, gc.LoginIntoNamespace(context.Background(),
50+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword, x.GalaxyNamespace))
51+
52+
hc, err := c.HTTPClient()
53+
require.NoError(t, err)
54+
require.NoError(t, hc.LoginIntoNamespace(dgraphapi.DefaultUser,
55+
dgraphapi.DefaultPassword, x.GalaxyNamespace))
56+
57+
rdfs := `
58+
_:a <dgraph.xid> "user1" .
59+
_:a <dgraph.type> "dgraph.type.User" .
60+
_:b <dgraph.xid> "user1" .
61+
_:b <dgraph.type> "dgraph.type.User" .`
62+
63+
mu := &api.Mutation{SetNquads: []byte(rdfs), CommitNow: true}
64+
_, err = gc.Mutate(mu)
65+
require.NoError(t, err)
66+
67+
var nss []uint64
68+
for i := 0; i < 5; i++ {
69+
ns, err := hc.AddNamespace()
70+
require.NoError(t, err)
71+
require.NoError(t, gc.LoginIntoNamespace(context.Background(), "groot", "password", ns))
72+
mu = &api.Mutation{SetNquads: []byte(rdfs), CommitNow: true}
73+
_, err = gc.Mutate(mu)
74+
require.NoError(t, err)
75+
nss = append(nss, ns)
76+
}
77+
78+
conf1 := dgraphtest.NewClusterConfig().WithNumAlphas(1).WithNumZeros(1).WithReplicas(1).WithACL(time.Hour).WithVersion("local")
79+
c1, err := dgraphtest.NewLocalCluster(conf1)
80+
require.NoError(t, err)
81+
defer func() { c1.Cleanup(t.Failed()) }()
82+
require.NoError(t, c1.Start())
83+
alphaHttp, err := c.GetAlphaHttpPublicPort()
84+
require.NoError(t, err)
85+
86+
args := []string{
87+
"checkupgrade",
88+
"--http_port", "localhost:" + alphaHttp,
89+
"--dgUser", "groot",
90+
"--password", "password",
91+
"--namespace", "1",
92+
}
93+
94+
cmd := exec.Command(filepath.Join(c1.GetTempDir(), "dgraph"), args...)
95+
out, err := cmd.CombinedOutput()
96+
require.NoError(t, err)
97+
actualOutput := string(out)
98+
fmt.Println("logs of checkupgrade tool\n", actualOutput)
99+
expectedOutputPattern := `Found duplicate users in namespace: #\d+\ndgraph\.xid user1 , Uids: \[\d+x\d+ \d+x\d+\]\n`
100+
match, err := regexp.MatchString(expectedOutputPattern, actualOutput)
101+
require.NoError(t, err)
102+
103+
if !match {
104+
t.Errorf("Output does not match expected pattern.\nExpected pattern:\n%s\n\nGot:\n%s",
105+
expectedOutputPattern, actualOutput)
106+
}
107+
}
108+
109+
func TestQueryDuplicateNodes(t *testing.T) {
110+
conf := dgraphtest.NewClusterConfig().WithNumAlphas(1).WithNumZeros(1).WithReplicas(1).
111+
WithACL(time.Hour).WithVersion("57aa5c4ac").WithAclAlg(jwt.GetSigningMethod("HS256"))
112+
c, err := dgraphtest.NewLocalCluster(conf)
113+
require.NoError(t, err)
114+
// defer func() { c.Cleanup(t.Failed()) }()
115+
require.NoError(t, c.Start())
116+
gc, cleanup, err := c.Client()
117+
require.NoError(t, err)
118+
defer cleanup()
119+
require.NoError(t, gc.LoginIntoNamespace(context.Background(),
120+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword, x.GalaxyNamespace))
121+
hc, err := c.HTTPClient()
122+
require.NoError(t, err)
123+
require.NoError(t, hc.LoginIntoNamespace(dgraphapi.DefaultUser,
124+
dgraphapi.DefaultPassword, x.GalaxyNamespace))
125+
rdfs := `
126+
<0x40> <dgraph.xid> "user1" .
127+
<0x40> <dgraph.type> "dgraph.type.User" .
128+
<0x50> <dgraph.xid> "user1" .
129+
<0x50> <dgraph.type> "dgraph.type.User" .
130+
<0x60> <dgraph.xid> "user1" .
131+
<0x60> <dgraph.type> "dgraph.type.User" .
132+
<0x60> <dgraph.user.group> <0x1> .
133+
<0x50> <dgraph.user.group> <0x1> .
134+
<0x70> <dgraph.xid> "user1" .
135+
<0x70> <dgraph.type> "dgraph.type.User" .
136+
<0x80> <dgraph.xid> "user3" .
137+
<0x80> <dgraph.type> "dgraph.type.User" .
138+
<0x90> <dgraph.xid> "user3" .
139+
<0x90> <dgraph.type> "dgraph.type.User" .
140+
<0x100> <dgraph.xid> "Group4" .
141+
<0x100> <dgraph.type> "dgraph.type.Group" .
142+
<0x110> <dgraph.xid> "Group4" .
143+
<0x110> <dgraph.type> "dgraph.type.Group" .
144+
<0x120> <dgraph.xid> "Group4" .
145+
<0x120> <dgraph.type> "dgraph.type.Group" .
146+
<0x130> <dgraph.xid> "Group4" .
147+
<0x130> <dgraph.type> "dgraph.type.Group" .
148+
<0x140> <dgraph.xid> "Group4" .
149+
<0x140> <dgraph.type> "dgraph.type.Group" .
150+
<0x150> <dgraph.xid> "usrgrp1" .
151+
<0x150> <dgraph.type> "dgraph.type.User" .
152+
<0x160> <dgraph.xid> "usrgrp1" .
153+
<0x160> <dgraph.type> "dgraph.type.User" .
154+
<0x170> <dgraph.xid> "usrgrp1" .
155+
<0x170> <dgraph.type> "dgraph.type.User" .
156+
<0x180> <dgraph.xid> "usrgrp1" .
157+
<0x180> <dgraph.type> "dgraph.type.Group" .
158+
<0x200> <dgraph.xid> "usrgrp2" .
159+
<0x200> <dgraph.type> "dgraph.type.Group" .
160+
<0x210> <dgraph.xid> "usrgrp2" .
161+
<0x210> <dgraph.type> "dgraph.type.User" .
162+
`
163+
mu := &api.Mutation{SetNquads: []byte(rdfs), CommitNow: true}
164+
_, err = gc.Mutate(mu)
165+
require.NoError(t, err)
166+
167+
duplicateNodes, err := queryDuplicateNodes(hc)
168+
require.NoError(t, err)
169+
170+
du := map[string][]string{
171+
"user1": {"0x40", "0x50", "0x60", "0x70"},
172+
"user3": {"0x80", "0x90"},
173+
"usrgrp1": {"0x150", "0x160", "0x170"},
174+
}
175+
176+
dg := map[string][]string{
177+
"Group4": {"0x100", "0x110", "0x120", "0x130", "0x140"},
178+
"usrgrp1": {"0x180", "0x190"},
179+
}
180+
181+
dug := map[string][]string{
182+
"usrgrp1": {"0x150", "0x160", "0x170", "0x180"},
183+
"usrgrp2": {"0x200", "0x210"},
184+
}
185+
186+
expectedDup := [3]map[string][]string{du, dg, dug}
187+
188+
for i, dn := range duplicateNodes {
189+
for j, d := range dn {
190+
require.Equal(t, len(expectedDup[i][j]), len(d))
191+
for _, uid := range d {
192+
require.Contains(t, expectedDup[i][j], uid)
193+
}
194+
}
195+
}
196+
require.NoError(t, deleteDuplicatesGroup(hc, duplicateNodes[0]))
197+
require.NoError(t, deleteDuplicatesGroup(hc, duplicateNodes[1]))
198+
require.NoError(t, deleteDuplicatesGroup(hc, duplicateNodes[2]))
199+
}

dgraph/cmd/root.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/spf13/cobra"
3333
"github.com/spf13/viper"
3434

35+
checkupgrade "github.com/dgraph-io/dgraph/check_upgrade"
3536
"github.com/dgraph-io/dgraph/dgraph/cmd/alpha"
3637
"github.com/dgraph-io/dgraph/dgraph/cmd/bulk"
3738
"github.com/dgraph-io/dgraph/dgraph/cmd/cert"
@@ -84,6 +85,7 @@ var rootConf = viper.New()
8485
var subcommands = []*x.SubCommand{
8586
&bulk.Bulk, &cert.Cert, &conv.Conv, &live.Live, &alpha.Alpha, &zero.Zero, &version.Version,
8687
&debug.Debug, &migrate.Migrate, &debuginfo.DebugInfo, &upgrade.Upgrade, &decrypt.Decrypt, &increment.Increment,
88+
&checkupgrade.CheckUpgrade,
8789
}
8890

8991
func initCmds() {

0 commit comments

Comments
 (0)