Skip to content

Commit f5f7650

Browse files
Add a test for RBE with executors talking to a Cache Proxy (#11342)
Related issues: buildbuddy-io/buildbuddy-internal#4539
1 parent 8ad88d6 commit f5f7650

File tree

4 files changed

+66
-9
lines changed

4 files changed

+66
-9
lines changed

enterprise/server/test/integration/cache_proxy/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ go_test(
1212
"//proto:encryption_go_proto",
1313
"//proto:remote_execution_go_proto",
1414
"//server/testutil/testkeys",
15+
"//server/util/authutil",
1516
"//server/util/claims",
17+
"//server/util/grpc_client",
1618
"//server/util/grpc_server",
1719
"//server/util/testing/flags",
1820
"@com_github_golang_jwt_jwt_v4//:jwt",

enterprise/server/test/integration/cache_proxy/cache_proxy_test.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@ package cache_proxy_test
22

33
import (
44
"context"
5+
"fmt"
6+
"runtime"
57
"strings"
68
"sync"
79
"testing"
810

911
"github.com/buildbuddy-io/buildbuddy/enterprise/server/test/integration/remote_execution/rbetest"
1012
"github.com/buildbuddy-io/buildbuddy/server/testutil/testkeys"
13+
"github.com/buildbuddy-io/buildbuddy/server/util/authutil"
1114
"github.com/buildbuddy-io/buildbuddy/server/util/claims"
15+
"github.com/buildbuddy-io/buildbuddy/server/util/grpc_client"
1216
"github.com/buildbuddy-io/buildbuddy/server/util/grpc_server"
1317
"github.com/buildbuddy-io/buildbuddy/server/util/testing/flags"
1418
"github.com/golang-jwt/jwt/v4"
@@ -40,13 +44,14 @@ func TestES256Auth(t *testing.T) {
4044
keyPair := testkeys.GenerateES256KeyPair(t)
4145
flags.Set(t, "auth.jwt_es256_private_key", keyPair.PrivateKeyPEM)
4246
flags.Set(t, "auth.remote.use_es256_jwts", true)
47+
flags.Set(t, "auth.reparse_jwts", false)
4348
require.NoError(t, claims.Init())
4449

4550
var mu sync.Mutex
4651
var capturedJWT string
4752
jwtInterceptor := func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
4853
if md, ok := metadata.FromIncomingContext(ctx); ok {
49-
if vals := md.Get("x-buildbuddy-jwt"); len(vals) > 0 {
54+
if vals := md.Get(authutil.ContextTokenStringKey); len(vals) > 0 {
5055
mu.Lock()
5156
capturedJWT = vals[len(vals)-1]
5257
mu.Unlock()
@@ -69,7 +74,7 @@ func TestES256Auth(t *testing.T) {
6974
},
7075
}
7176

72-
ctx := metadata.AppendToOutgoingContext(t.Context(), "x-buildbuddy-api-key", rbe.APIKey1)
77+
ctx := metadata.AppendToOutgoingContext(t.Context(), authutil.APIKeyHeader, rbe.APIKey1)
7378
resp, err := cas.FindMissingBlobs(ctx, &req)
7479
require.NoError(t, err)
7580
require.Equal(t, 1, len(resp.MissingBlobDigests))
@@ -84,6 +89,42 @@ func TestES256Auth(t *testing.T) {
8489
require.Equal(t, "ES256", token.Method.Alg())
8590
}
8691

92+
func TestES256Auth_RemoteExecution(t *testing.T) {
93+
// TODO(http://go/b/4539): enable this test
94+
t.Skip()
95+
96+
keyPair := testkeys.GenerateES256KeyPair(t)
97+
flags.Set(t, "auth.jwt_es256_private_key", keyPair.PrivateKeyPEM)
98+
flags.Set(t, "auth.remote.use_es256_jwts", true)
99+
flags.Set(t, "auth.reparse_jwts", false)
100+
require.NoError(t, claims.Init())
101+
102+
rbe := rbetest.NewRBETestEnv(t)
103+
rbe.AddBuildBuddyServer()
104+
proxy := rbe.AddCacheProxy()
105+
conn, err := grpc_client.DialSimple(
106+
fmt.Sprintf("grpc://localhost:%d", proxy.Port))
107+
require.NoError(t, err)
108+
rbe.AddExecutorWithOptions(t, &rbetest.ExecutorOptions{
109+
Name: "executor",
110+
CacheConn: conn,
111+
})
112+
113+
cmd := rbe.Execute(&repb.Command{
114+
Arguments: []string{"sh", "-c", "echo hello"},
115+
Platform: &repb.Platform{
116+
Properties: []*repb.Platform_Property{
117+
{Name: "container-image", Value: "none"},
118+
{Name: "OSFamily", Value: runtime.GOOS},
119+
{Name: "Arch", Value: runtime.GOARCH},
120+
},
121+
},
122+
}, &rbetest.ExecuteOpts{APIKey: rbe.APIKey1})
123+
res := cmd.Wait()
124+
require.Equal(t, 0, res.ExitCode)
125+
require.Equal(t, "hello\n", res.Stdout)
126+
}
127+
87128
func TestFindMissing_Encryption(t *testing.T) {
88129
rbe := rbetest.NewRBETestEnv(t)
89130
rbe.AddBuildBuddyServer()
@@ -97,7 +138,7 @@ func TestFindMissing_Encryption(t *testing.T) {
97138
},
98139
}
99140

100-
ctx := metadata.AppendToOutgoingContext(t.Context(), "x-buildbuddy-api-key", rbe.APIKey1)
141+
ctx := metadata.AppendToOutgoingContext(t.Context(), authutil.APIKeyHeader, rbe.APIKey1)
101142
resp, err := cas.FindMissingBlobs(ctx, &req)
102143
require.NoError(t, err)
103144
require.Equal(t, 1, len(resp.MissingBlobDigests))

enterprise/server/test/integration/remote_execution/rbetest/rbetest.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,9 @@ type ExecutorOptions struct {
710710
APIKey string
711711
// Optional Pool name for the executor
712712
Pool string
713+
// Optional connection for the executor to use for CAS/AC/ByteStream.
714+
// Defaults to the app proxy connection if unset.
715+
CacheConn grpc.ClientConnInterface
713716
// Optional interceptor for command execution results.
714717
RunInterceptor
715718
priorityTaskSchedulerOptions priority_task_scheduler.Options
@@ -859,11 +862,16 @@ func (r *Env) addExecutor(t testing.TB, options *ExecutorOptions) *Executor {
859862
clientConn := r.appProxyConn
860863
env.SetSchedulerClient(scpb.NewSchedulerClient(clientConn))
861864
env.SetRemoteExecutionClient(repb.NewExecutionClient(clientConn))
862-
env.SetActionCacheClient(repb.NewActionCacheClient(clientConn))
863-
env.SetContentAddressableStorageClient(repb.NewContentAddressableStorageClient(clientConn))
864-
env.SetByteStreamClient(bspb.NewByteStreamClient(clientConn))
865865
env.SetCapabilitiesClient(repb.NewCapabilitiesClient(clientConn))
866866

867+
cacheConn := grpc.ClientConnInterface(clientConn)
868+
if options.CacheConn != nil {
869+
cacheConn = options.CacheConn
870+
}
871+
env.SetActionCacheClient(repb.NewActionCacheClient(cacheConn))
872+
env.SetContentAddressableStorageClient(repb.NewContentAddressableStorageClient(cacheConn))
873+
env.SetByteStreamClient(bspb.NewByteStreamClient(cacheConn))
874+
867875
env.SetAuthenticator(r.testEnv.GetAuthenticator())
868876
xl := xcode.NewXcodeLocator()
869877
env.SetXcodeLocator(xl)
@@ -976,7 +984,7 @@ func (r *Env) waitForExecutorRegistration() {
976984
type CacheProxy struct {
977985
t testing.TB
978986
env *testenv.TestEnv
979-
port int
987+
Port int
980988
conn *grpc_client.ClientConnPool
981989
}
982990

@@ -1036,7 +1044,7 @@ func (r *Env) AddCacheProxy() *CacheProxy {
10361044
// Finally, create the client connection.
10371045
conn, err := grpc_client.DialSimple(fmt.Sprintf("grpc://localhost:%d", port))
10381046
require.NoError(r.t, err)
1039-
return &CacheProxy{t: r.t, env: proxyEnv, conn: conn}
1047+
return &CacheProxy{t: r.t, env: proxyEnv, Port: port, conn: conn}
10401048
}
10411049

10421050
func (r *Env) DownloadOutputsToNewTempDir(res *CommandResult) string {

server/testutil/testauth/testauth.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,13 @@ func RequestContext(userID string, groupID string) *ctxpb.RequestContext {
219219

220220
// WithAuthenticatedUserInfo sets the authenticated user to the given user.
221221
func WithAuthenticatedUserInfo(ctx context.Context, userInfo interfaces.UserInfo) context.Context {
222-
jwt, err := claims.AssembleJWT(userInfo.(*claims.Claims), jwt.SigningMethodHS256)
222+
// Copy claims to avoid mutating shared state when AssembleJWT sets standard
223+
// claims, then set them in context to avoid reparsing.
224+
newClaims := *userInfo.(*claims.Claims)
225+
c := &newClaims
226+
ctx = claims.AuthContext(ctx, c)
227+
228+
jwt, err := claims.AssembleJWT(c, jwt.SigningMethodHS256)
223229
if err != nil {
224230
log.Errorf("Failed to mint JWT from UserInfo: %s", err)
225231
return ctx

0 commit comments

Comments
 (0)