Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions cmd/bb_remote_asset/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func main() {
if err != nil {
return util.StatusWrap(err, "Failed to create CAS blob access")
}

var assetStore storage.AssetStore
if config.AssetCache != nil {
assetStore, err = configuration.NewAssetStoreFromConfiguration(
Expand All @@ -78,8 +79,6 @@ func main() {
grpcClientFactory,
int(config.MaximumMessageSizeBytes),
dependenciesGroup,
fetchAuthorizer,
pushAuthorizer,
)
if err != nil {
return util.StatusWrap(err, "Failed to create asset store")
Expand Down Expand Up @@ -113,12 +112,13 @@ func main() {
pushServer := push.NewAssetPushServer(
assetStore,
allowUpdatesForInstances)
pushServer = push.NewAuthorizingPushServer(pushServer, pushAuthorizer)
metricsPushServer = push.NewMetricsAssetPushServer(pushServer, clock.SystemClock, "push")
} else {
metricsPushServer = push.NewErrorPushServer(&protostatus.Status{
metricsPushServer = push.NewAuthorizingPushServer(push.NewErrorPushServer(&protostatus.Status{
Code: int32(codes.FailedPrecondition),
Message: "Server is not configured to allow pushing assets",
})
}), pushAuthorizer)
}

// Spawn gRPC servers for client and worker traffic.
Expand Down
11 changes: 11 additions & 0 deletions internal/mock/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ gomock(
package = "mock",
)

gomock(
name = "push",
out = "push.go",
interfaces = [
"PushServer",
],
library = "@bazel_remote_apis//build/bazel/remote/asset/v1:remote_asset_go_proto",
package = "mock",
)

gomock(
name = "storage",
out = "storage.go",
Expand All @@ -56,6 +66,7 @@ go_library(
"blobstore.go",
"dummy.go",
"fetcher.go",
"push.go",
"storage.go",
],
importpath = "github.com/buildbarn/bb-remote-asset/internal/mock",
Expand Down
5 changes: 1 addition & 4 deletions pkg/configuration/new_asset_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
pb "github.com/buildbarn/bb-remote-asset/pkg/proto/configuration/bb_remote_asset"
"github.com/buildbarn/bb-remote-asset/pkg/storage"
asset_configuration "github.com/buildbarn/bb-remote-asset/pkg/storage/blobstore"
"github.com/buildbarn/bb-storage/pkg/auth"
blobstore_configuration "github.com/buildbarn/bb-storage/pkg/blobstore/configuration"
"github.com/buildbarn/bb-storage/pkg/grpc"
"github.com/buildbarn/bb-storage/pkg/program"
Expand All @@ -21,8 +20,6 @@ func NewAssetStoreFromConfiguration(
grpcClientFactory grpc.ClientFactory,
maximumMessageSizeBytes int,
dependenciesGroup program.Group,
fetchAuthorizer auth.Authorizer,
pushAuthorizer auth.Authorizer,
) (storage.AssetStore, error) {
var assetStore storage.AssetStore
switch backend := configuration.Backend.(type) {
Expand Down Expand Up @@ -56,5 +53,5 @@ func NewAssetStoreFromConfiguration(
default:
return nil, status.Errorf(codes.InvalidArgument, "Asset Cache configuration is invalid as no supported Asset Cache is defined.")
}
return storage.NewAuthorizingAssetStore(assetStore, fetchAuthorizer, pushAuthorizer), nil
return assetStore, nil
}
8 changes: 7 additions & 1 deletion pkg/push/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ load("@rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "push",
srcs = [
"authorizing_push_server.go",
"error_push_server.go",
"metrics_push_server.go",
"push_server.go",
Expand All @@ -13,6 +14,7 @@ go_library(
"//pkg/storage",
"@bazel_remote_apis//build/bazel/remote/asset/v1:remote_asset_go_proto",
"@bazel_remote_apis//build/bazel/remote/execution/v2:remote_execution_go_proto",
"@com_github_buildbarn_bb_storage//pkg/auth",
"@com_github_buildbarn_bb_storage//pkg/clock",
"@com_github_buildbarn_bb_storage//pkg/digest",
"@com_github_buildbarn_bb_storage//pkg/util",
Expand All @@ -25,7 +27,10 @@ go_library(

go_test(
name = "push_test",
srcs = ["push_server_test.go"],
srcs = [
"authorizing_push_server_test.go",
"push_server_test.go",
],
deps = [
":push",
"//internal/mock",
Expand All @@ -35,6 +40,7 @@ go_test(
"@bazel_remote_apis//build/bazel/remote/execution/v2:remote_execution_go_proto",
"@com_github_buildbarn_bb_storage//pkg/blobstore/buffer",
"@com_github_buildbarn_bb_storage//pkg/digest",
"@com_github_buildbarn_bb_storage//pkg/util",
"@com_github_golang_mock//gomock",
"@com_github_stretchr_testify//require",
"@org_golang_google_grpc//codes",
Expand Down
47 changes: 47 additions & 0 deletions pkg/push/authorizing_push_server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package push

import (
"context"

remoteasset "github.com/bazelbuild/remote-apis/build/bazel/remote/asset/v1"
"github.com/buildbarn/bb-storage/pkg/auth"
"github.com/buildbarn/bb-storage/pkg/digest"
)

// AuthorizingPushServer decorates a PushServer and validates the requests against an Authorizer
type AuthorizingPushServer struct {
remoteasset.PushServer
authorizer auth.Authorizer
}

// NewAuthorizingPushServer wraps a PushServer into an AuthorizingPushServer
func NewAuthorizingPushServer(p remoteasset.PushServer, authorizer auth.Authorizer) *AuthorizingPushServer {
return &AuthorizingPushServer{
p,
authorizer,
}
}

// PushBlob authorizes a PushBlob request and, if successful, passes it along to the wrapped PushServer
func (ap *AuthorizingPushServer) PushBlob(ctx context.Context, req *remoteasset.PushBlobRequest) (*remoteasset.PushBlobResponse, error) {
instanceName, err := digest.NewInstanceName(req.InstanceName)
if err != nil {
return nil, err
}
if err = auth.AuthorizeSingleInstanceName(ctx, ap.authorizer, instanceName); err != nil {
return nil, err
}
return ap.PushServer.PushBlob(ctx, req)
}

// PushDirectory authorizes a PushDirectory request and, if successful, passes it along to the wrapped PushServer
func (ap *AuthorizingPushServer) PushDirectory(ctx context.Context, req *remoteasset.PushDirectoryRequest) (*remoteasset.PushDirectoryResponse, error) {
instanceName, err := digest.NewInstanceName(req.InstanceName)
if err != nil {
return nil, err
}
if err = auth.AuthorizeSingleInstanceName(ctx, ap.authorizer, instanceName); err != nil {
return nil, err
}
return ap.PushServer.PushDirectory(ctx, req)
}
91 changes: 91 additions & 0 deletions pkg/push/authorizing_push_server_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package push_test

import (
"context"
"testing"

remoteasset "github.com/bazelbuild/remote-apis/build/bazel/remote/asset/v1"
remoteexecution "github.com/bazelbuild/remote-apis/build/bazel/remote/execution/v2"
"github.com/buildbarn/bb-remote-asset/internal/mock"
"github.com/buildbarn/bb-remote-asset/pkg/push"
bb_digest "github.com/buildbarn/bb-storage/pkg/digest"
"github.com/buildbarn/bb-storage/pkg/util"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func TestPushBlobAuthorization(t *testing.T) {
ctrl, ctx := gomock.WithContext(context.Background(), t)

basePushServer := mock.NewMockPushServer(ctrl)
authorizer := mock.NewMockAuthorizer(ctrl)
ap := push.NewAuthorizingPushServer(basePushServer, authorizer)

instanceName := util.Must(bb_digest.NewInstanceName("ithilien"))
instanceSlice := []bb_digest.InstanceName{instanceName}

uri := "source.test"
blobDigest := &remoteexecution.Digest{Hash: "d0d829c4c0ce64787cb1c998a9c29a109f8ed005633132fda4f29982487b04db", SizeBytes: 123}
request := &remoteasset.PushBlobRequest{
InstanceName: "ithilien",
Uris: []string{uri},
BlobDigest: blobDigest,
}

wantResp := &remoteasset.PushBlobResponse{}

t.Run("Allowed", func(t *testing.T) {
authorizer.EXPECT().Authorize(ctx, instanceSlice).Return([]error{nil})
basePushServer.EXPECT().PushBlob(ctx, request).Return(wantResp, nil)

gotResp, err := ap.PushBlob(ctx, request)
require.NoError(t, err)
require.Equal(t, wantResp, gotResp)
})

t.Run("Rejected", func(t *testing.T) {
authorizer.EXPECT().Authorize(ctx, instanceSlice).Return([]error{status.Error(codes.PermissionDenied, "You shall not pass")})

_, err := ap.PushBlob(ctx, request)
require.Equal(t, err, status.Error(codes.PermissionDenied, "You shall not pass"))
})
}

func TestPushDirectoryAuthorization(t *testing.T) {
ctrl, ctx := gomock.WithContext(context.Background(), t)

basePushServer := mock.NewMockPushServer(ctrl)
authorizer := mock.NewMockAuthorizer(ctrl)
ap := push.NewAuthorizingPushServer(basePushServer, authorizer)

instanceName := util.Must(bb_digest.NewInstanceName("ithilien"))
instanceSlice := []bb_digest.InstanceName{instanceName}

uri := "source.test"
directoryDigest := &remoteexecution.Digest{Hash: "d0d829c4c0ce64787cb1c998a9c29a109f8ed005633132fda4f29982487b04db", SizeBytes: 123}
request := &remoteasset.PushDirectoryRequest{
InstanceName: "ithilien",
Uris: []string{uri},
RootDirectoryDigest: directoryDigest,
}

wantResp := &remoteasset.PushDirectoryResponse{}

t.Run("Allowed", func(t *testing.T) {
authorizer.EXPECT().Authorize(ctx, instanceSlice).Return([]error{nil})
basePushServer.EXPECT().PushDirectory(ctx, request).Return(wantResp, nil)

gotResp, err := ap.PushDirectory(ctx, request)
require.NoError(t, err)
require.Equal(t, wantResp, gotResp)
})

t.Run("Rejected", func(t *testing.T) {
authorizer.EXPECT().Authorize(ctx, instanceSlice).Return([]error{status.Error(codes.PermissionDenied, "You shall not pass")})

_, err := ap.PushDirectory(ctx, request)
require.Equal(t, err, status.Error(codes.PermissionDenied, "You shall not pass"))
})
}
3 changes: 0 additions & 3 deletions pkg/storage/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ go_library(
"asset.go",
"asset_reference.go",
"asset_store.go",
"authorizing_asset_store.go",
"blob_access_asset_store.go",
"digest.go",
],
Expand All @@ -18,7 +17,6 @@ go_library(
"//pkg/qualifier",
"@bazel_remote_apis//build/bazel/remote/asset/v1:remote_asset_go_proto",
"@bazel_remote_apis//build/bazel/remote/execution/v2:remote_execution_go_proto",
"@com_github_buildbarn_bb_storage//pkg/auth",
"@com_github_buildbarn_bb_storage//pkg/blobstore",
"@com_github_buildbarn_bb_storage//pkg/blobstore/buffer",
"@com_github_buildbarn_bb_storage//pkg/digest",
Expand All @@ -35,7 +33,6 @@ go_test(
srcs = [
"action_cache_asset_store_test.go",
"asset_reference_test.go",
"authorizing_asset_store_test.go",
"blob_access_asset_store_test.go",
],
deps = [
Expand Down
41 changes: 0 additions & 41 deletions pkg/storage/authorizing_asset_store.go

This file was deleted.

Loading