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

Commit 4ad9fcf

Browse files
authored
gitserver: Move subrepoperms checks back to client (#62022)
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 8a0b342 commit 4ad9fcf

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
@@ -41,7 +41,6 @@ go_library(
4141
"//cmd/gitserver/internal/vcssyncer",
4242
"//internal/actor",
4343
"//internal/api",
44-
"//internal/authz",
4544
"//internal/conf",
4645
"//internal/database",
4746
"//internal/diskusage",
@@ -73,7 +72,6 @@ go_library(
7372
"//internal/wrexec",
7473
"//lib/errors",
7574
"//lib/gitservice",
76-
"//lib/pointers",
7775
"@com_github_mxk_go_flowrate//flowrate",
7876
"@com_github_prometheus_client_golang//prometheus",
7977
"@com_github_prometheus_client_golang//prometheus/promauto",
@@ -117,7 +115,6 @@ go_test(
117115
"//cmd/gitserver/internal/vcssyncer",
118116
"//internal/actor",
119117
"//internal/api",
120-
"//internal/authz",
121118
"//internal/conf",
122119
"//internal/database",
123120
"//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 {
@@ -52,7 +49,6 @@ func NewGRPCServer(server *Server, config *GRPCServerConfig) proto.GitserverServ
5249
logger: server.logger,
5350
db: server.db,
5451
hostname: server.hostname,
55-
subRepoChecker: authz.DefaultSubRepoPermsChecker,
5652
locker: server.locker,
5753
getBackendFunc: server.getBackendFunc,
5854
svc: server,
@@ -75,7 +71,6 @@ type grpcServer struct {
7571
logger log.Logger
7672
db database.DB
7773
hostname string
78-
subRepoChecker authz.SubRepoPermissionChecker
7974
locker RepositoryLocker
8075
getBackendFunc Backender
8176
fs gitserverfs.FS
@@ -284,15 +279,6 @@ func (gs *grpcServer) Archive(req *proto.ArchiveRequest, ss proto.GitserverServi
284279
return err
285280
}
286281

287-
if !actor.FromContext(ctx).IsInternal() {
288-
if enabled, err := gs.subRepoChecker.EnabledForRepo(ctx, repoName); err != nil {
289-
return errors.Wrap(err, "sub-repo permissions check")
290-
} else if enabled {
291-
s := status.New(codes.Unimplemented, "archiveReader invoked for a repo with sub-repo permissions")
292-
return s.Err()
293-
}
294-
}
295-
296282
// This is a long time, but this never blocks a user request for this
297283
// long. Even repos that are not that large can take a long time, for
298284
// example a search over all repos in an organization may have several
@@ -803,14 +789,9 @@ func (gs *grpcServer) GetCommit(ctx context.Context, req *proto.GetCommitRequest
803789
return nil, err
804790
}
805791

806-
subRepoPermsEnabled, err := authz.SubRepoEnabledForRepo(ctx, gs.subRepoChecker, repoName)
807-
if err != nil {
808-
return nil, err
809-
}
810-
811792
backend := gs.getBackendFunc(repoDir, repoName)
812793

813-
commit, err := backend.GetCommit(ctx, api.CommitID(req.GetCommit()), subRepoPermsEnabled)
794+
commit, err := backend.GetCommit(ctx, api.CommitID(req.GetCommit()), req.GetIncludeModifiedFiles())
814795
if err != nil {
815796
var e *gitdomain.RevisionNotFoundError
816797
if errors.As(err, &e) {
@@ -828,24 +809,14 @@ func (gs *grpcServer) GetCommit(ctx context.Context, req *proto.GetCommitRequest
828809
return nil, err
829810
}
830811

831-
hasAccess, err := hasAccessToCommit(ctx, repoName, commit.ModifiedFiles, gs.subRepoChecker)
832-
if err != nil {
833-
return nil, err
834-
}
835-
836-
if !hasAccess {
837-
s, err := status.New(codes.NotFound, "revision not found").WithDetails(&proto.RevisionNotFoundPayload{
838-
Repo: req.GetRepoName(),
839-
Spec: req.GetCommit(),
840-
})
841-
if err != nil {
842-
return nil, err
843-
}
844-
return nil, s.Err()
812+
modifiedFiles := make([][]byte, len(commit.ModifiedFiles))
813+
for i, f := range commit.ModifiedFiles {
814+
modifiedFiles[i] = []byte(f)
845815
}
846816

847817
return &proto.GetCommitResponse{
848-
Commit: commit.ToProto(),
818+
Commit: commit.ToProto(),
819+
ModifiedFiles: modifiedFiles,
849820
}, nil
850821
}
851822

@@ -878,26 +849,6 @@ func (gs *grpcServer) Blame(req *proto.BlameRequest, ss proto.GitserverService_B
878849
return err
879850
}
880851

881-
// First, verify that the actor has access to the given path.
882-
hasAccess, err := authz.FilterActorPath(ctx, gs.subRepoChecker, actor.FromContext(ctx), repoName, req.GetPath())
883-
if err != nil {
884-
return err
885-
}
886-
if !hasAccess {
887-
up := &proto.UnauthorizedPayload{
888-
RepoName: req.GetRepoName(),
889-
Commit: pointers.Ptr(req.GetCommit()),
890-
Path: pointers.Ptr(req.GetPath()),
891-
}
892-
893-
s, marshalErr := status.New(codes.PermissionDenied, "no access to path").WithDetails(up)
894-
if marshalErr != nil {
895-
gs.logger.Error("failed to marshal error", log.Error(marshalErr))
896-
return err
897-
}
898-
return s.Err()
899-
}
900-
901852
backend := gs.getBackendFunc(repoDir, repoName)
902853

903854
opts := git.BlameOptions{
@@ -1038,27 +989,6 @@ func (gs *grpcServer) ReadFile(req *proto.ReadFileRequest, ss proto.GitserverSer
1038989
return err
1039990
}
1040991

1041-
// First, verify that the actor has access to the given path.
1042-
hasAccess, err := authz.FilterActorPath(ctx, gs.subRepoChecker, actor.FromContext(ctx), repoName, req.GetPath())
1043-
if err != nil {
1044-
return err
1045-
}
1046-
if !hasAccess {
1047-
up := &proto.UnauthorizedPayload{
1048-
RepoName: req.GetRepoName(),
1049-
Path: pointers.Ptr(req.GetPath()),
1050-
}
1051-
if c := req.GetCommit(); c != "" {
1052-
up.Commit = &c
1053-
}
1054-
s, marshalErr := status.New(codes.PermissionDenied, "no access to path").WithDetails(up)
1055-
if marshalErr != nil {
1056-
gs.logger.Error("failed to marshal error", log.Error(marshalErr))
1057-
return err
1058-
}
1059-
return s.Err()
1060-
}
1061-
1062992
backend := gs.getBackendFunc(repoDir, repoName)
1063993

1064994
r, err := backend.ReadFile(ctx, api.CommitID(req.GetCommit()), req.GetPath())
@@ -1445,29 +1375,6 @@ func (gs *grpcServer) checkRepoExists(ctx context.Context, repo api.RepoName) er
14451375
return newRepoNotFoundError(repo, cloneInProgress, cloneProgress)
14461376
}
14471377

1448-
func hasAccessToCommit(ctx context.Context, repoName api.RepoName, files []string, checker authz.SubRepoPermissionChecker) (bool, error) {
1449-
if len(files) == 0 {
1450-
return true, nil // If commit has no files, assume user has access to view the commit.
1451-
}
1452-
1453-
if enabled, err := authz.SubRepoEnabledForRepo(ctx, checker, repoName); err != nil {
1454-
return false, err
1455-
} else if !enabled {
1456-
return true, nil
1457-
}
1458-
1459-
a := actor.FromContext(ctx)
1460-
for _, fileName := range files {
1461-
if hasAccess, err := authz.FilterActorPath(ctx, checker, a, repoName, fileName); err != nil {
1462-
return false, err
1463-
} else if hasAccess {
1464-
// if the user has access to one file modified in the commit, they have access to view the commit
1465-
return true, nil
1466-
}
1467-
}
1468-
return false, nil
1469-
}
1470-
14711378
func newRepoNotFoundError(repo api.RepoName, cloneInProgress bool, cloneProgress string) error {
14721379
s, err := status.New(codes.NotFound, "repo not found").WithDetails(&proto.RepoNotFoundPayload{
14731380
CloneInProgress: cloneInProgress,

0 commit comments

Comments
 (0)