Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Commit 02b05dc

Browse files
committed
gitserver: Move subrepoperms checks back to client
While starting this migration, it felt nice to move sub repo permission checks to the server side, because that means we can make certain optimizations and none of the clients need to reimplement the SRP checker implementation. However, this moves sub repo authz over the wire, but doesn't move repo perms generally here, so this was a weird split. This also unnecessarily couples Sourcegraph and gitserver, so for now this is going back into the client layer, like all the auth checks. Please make sure to pay good attention to the backend and client implementation and help me validate that those are indeed equal. Test plan: Added tests, E2E perforce subrepo perms tests are still passing.
1 parent 51235ab commit 02b05dc

File tree

9 files changed

+1414
-1621
lines changed

9 files changed

+1414
-1621
lines changed

cmd/gitserver/internal/BUILD.bazel

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ go_library(
3939
"//cmd/gitserver/internal/vcssyncer",
4040
"//internal/actor",
4141
"//internal/api",
42-
"//internal/authz",
4342
"//internal/conf",
4443
"//internal/database",
4544
"//internal/diskusage",
@@ -70,7 +69,6 @@ go_library(
7069
"//internal/wrexec",
7170
"//lib/errors",
7271
"//lib/gitservice",
73-
"//lib/pointers",
7472
"@com_github_mxk_go_flowrate//flowrate",
7573
"@com_github_prometheus_client_golang//prometheus",
7674
"@com_github_prometheus_client_golang//prometheus/promauto",
@@ -113,7 +111,6 @@ go_test(
113111
"//cmd/gitserver/internal/vcssyncer",
114112
"//internal/actor",
115113
"//internal/api",
116-
"//internal/authz",
117114
"//internal/conf",
118115
"//internal/database",
119116
"//internal/database/dbmocks",

cmd/gitserver/internal/server_grpc.go

Lines changed: 6 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ import (
1818
"github.com/sourcegraph/sourcegraph/cmd/gitserver/internal/git/gitcli"
1919
"github.com/sourcegraph/sourcegraph/cmd/gitserver/internal/gitserverfs"
2020
"github.com/sourcegraph/sourcegraph/cmd/gitserver/internal/perforce"
21-
"github.com/sourcegraph/sourcegraph/internal/actor"
2221
"github.com/sourcegraph/sourcegraph/internal/api"
23-
"github.com/sourcegraph/sourcegraph/internal/authz"
2422
"github.com/sourcegraph/sourcegraph/internal/conf"
2523
"github.com/sourcegraph/sourcegraph/internal/database"
2624
"github.com/sourcegraph/sourcegraph/internal/dotcom"
@@ -32,7 +30,6 @@ import (
3230
"github.com/sourcegraph/sourcegraph/internal/repoupdater"
3331
"github.com/sourcegraph/sourcegraph/internal/trace"
3432
"github.com/sourcegraph/sourcegraph/lib/errors"
35-
"github.com/sourcegraph/sourcegraph/lib/pointers"
3633
)
3734

3835
type service interface {
@@ -48,7 +45,6 @@ func NewGRPCServer(server *Server) proto.GitserverServiceServer {
4845
logger: server.logger,
4946
db: server.db,
5047
hostname: server.hostname,
51-
subRepoChecker: authz.DefaultSubRepoPermsChecker,
5248
locker: server.locker,
5349
getBackendFunc: server.getBackendFunc,
5450
svc: server,
@@ -60,7 +56,6 @@ type grpcServer struct {
6056
logger log.Logger
6157
db database.DB
6258
hostname string
63-
subRepoChecker authz.SubRepoPermissionChecker
6459
locker RepositoryLocker
6560
getBackendFunc Backender
6661
fs gitserverfs.FS
@@ -269,15 +264,6 @@ func (gs *grpcServer) Archive(req *proto.ArchiveRequest, ss proto.GitserverServi
269264
return err
270265
}
271266

272-
if !actor.FromContext(ctx).IsInternal() {
273-
if enabled, err := gs.subRepoChecker.EnabledForRepo(ctx, repoName); err != nil {
274-
return errors.Wrap(err, "sub-repo permissions check")
275-
} else if enabled {
276-
s := status.New(codes.Unimplemented, "archiveReader invoked for a repo with sub-repo permissions")
277-
return s.Err()
278-
}
279-
}
280-
281267
// This is a long time, but this never blocks a user request for this
282268
// long. Even repos that are not that large can take a long time, for
283269
// example a search over all repos in an organization may have several
@@ -788,14 +774,9 @@ func (gs *grpcServer) GetCommit(ctx context.Context, req *proto.GetCommitRequest
788774
return nil, err
789775
}
790776

791-
subRepoPermsEnabled, err := authz.SubRepoEnabledForRepo(ctx, gs.subRepoChecker, repoName)
792-
if err != nil {
793-
return nil, err
794-
}
795-
796777
backend := gs.getBackendFunc(repoDir, repoName)
797778

798-
commit, err := backend.GetCommit(ctx, api.CommitID(req.GetCommit()), subRepoPermsEnabled)
779+
commit, err := backend.GetCommit(ctx, api.CommitID(req.GetCommit()), req.GetIncludeModifiedFiles())
799780
if err != nil {
800781
var e *gitdomain.RevisionNotFoundError
801782
if errors.As(err, &e) {
@@ -813,24 +794,14 @@ func (gs *grpcServer) GetCommit(ctx context.Context, req *proto.GetCommitRequest
813794
return nil, err
814795
}
815796

816-
hasAccess, err := hasAccessToCommit(ctx, repoName, commit.ModifiedFiles, gs.subRepoChecker)
817-
if err != nil {
818-
return nil, err
819-
}
820-
821-
if !hasAccess {
822-
s, err := status.New(codes.NotFound, "revision not found").WithDetails(&proto.RevisionNotFoundPayload{
823-
Repo: req.GetRepoName(),
824-
Spec: req.GetCommit(),
825-
})
826-
if err != nil {
827-
return nil, err
828-
}
829-
return nil, s.Err()
797+
modifiedFiles := make([][]byte, len(commit.ModifiedFiles))
798+
for i, f := range commit.ModifiedFiles {
799+
modifiedFiles[i] = []byte(f)
830800
}
831801

832802
return &proto.GetCommitResponse{
833-
Commit: commit.ToProto(),
803+
Commit: commit.ToProto(),
804+
ModifiedFiles: modifiedFiles,
834805
}, nil
835806
}
836807

@@ -863,26 +834,6 @@ func (gs *grpcServer) Blame(req *proto.BlameRequest, ss proto.GitserverService_B
863834
return err
864835
}
865836

866-
// First, verify that the actor has access to the given path.
867-
hasAccess, err := authz.FilterActorPath(ctx, gs.subRepoChecker, actor.FromContext(ctx), repoName, req.GetPath())
868-
if err != nil {
869-
return err
870-
}
871-
if !hasAccess {
872-
up := &proto.UnauthorizedPayload{
873-
RepoName: req.GetRepoName(),
874-
Commit: pointers.Ptr(req.GetCommit()),
875-
Path: pointers.Ptr(req.GetPath()),
876-
}
877-
878-
s, marshalErr := status.New(codes.PermissionDenied, "no access to path").WithDetails(up)
879-
if marshalErr != nil {
880-
gs.logger.Error("failed to marshal error", log.Error(marshalErr))
881-
return err
882-
}
883-
return s.Err()
884-
}
885-
886837
backend := gs.getBackendFunc(repoDir, repoName)
887838

888839
opts := git.BlameOptions{
@@ -1023,27 +974,6 @@ func (gs *grpcServer) ReadFile(req *proto.ReadFileRequest, ss proto.GitserverSer
1023974
return err
1024975
}
1025976

1026-
// First, verify that the actor has access to the given path.
1027-
hasAccess, err := authz.FilterActorPath(ctx, gs.subRepoChecker, actor.FromContext(ctx), repoName, req.GetPath())
1028-
if err != nil {
1029-
return err
1030-
}
1031-
if !hasAccess {
1032-
up := &proto.UnauthorizedPayload{
1033-
RepoName: req.GetRepoName(),
1034-
Path: pointers.Ptr(req.GetPath()),
1035-
}
1036-
if c := req.GetCommit(); c != "" {
1037-
up.Commit = &c
1038-
}
1039-
s, marshalErr := status.New(codes.PermissionDenied, "no access to path").WithDetails(up)
1040-
if marshalErr != nil {
1041-
gs.logger.Error("failed to marshal error", log.Error(marshalErr))
1042-
return err
1043-
}
1044-
return s.Err()
1045-
}
1046-
1047977
backend := gs.getBackendFunc(repoDir, repoName)
1048978

1049979
r, err := backend.ReadFile(ctx, api.CommitID(req.GetCommit()), req.GetPath())
@@ -1430,29 +1360,6 @@ func (gs *grpcServer) checkRepoExists(ctx context.Context, repo api.RepoName) er
14301360
return newRepoNotFoundError(repo, cloneInProgress, cloneProgress)
14311361
}
14321362

1433-
func hasAccessToCommit(ctx context.Context, repoName api.RepoName, files []string, checker authz.SubRepoPermissionChecker) (bool, error) {
1434-
if len(files) == 0 {
1435-
return true, nil // If commit has no files, assume user has access to view the commit.
1436-
}
1437-
1438-
if enabled, err := authz.SubRepoEnabledForRepo(ctx, checker, repoName); err != nil {
1439-
return false, err
1440-
} else if !enabled {
1441-
return true, nil
1442-
}
1443-
1444-
a := actor.FromContext(ctx)
1445-
for _, fileName := range files {
1446-
if hasAccess, err := authz.FilterActorPath(ctx, checker, a, repoName, fileName); err != nil {
1447-
return false, err
1448-
} else if hasAccess {
1449-
// if the user has access to one file modified in the commit, they have access to view the commit
1450-
return true, nil
1451-
}
1452-
}
1453-
return false, nil
1454-
}
1455-
14561363
func newRepoNotFoundError(repo api.RepoName, cloneInProgress bool, cloneProgress string) error {
14571364
s, err := status.New(codes.NotFound, "repo not found").WithDetails(&proto.RepoNotFoundPayload{
14581365
CloneInProgress: cloneInProgress,

0 commit comments

Comments
 (0)