Skip to content

Commit add8296

Browse files
committed
feat(grpc): allow files to be read by jmespath expressions
This allows allow jmespath expressions to refer to the contents of certain pre-declared files which are reloaded on a user-specified schedule. For example, if you want to use k8s bound service account tokens you could add the following to your Pod: volumes: - name: token-vol projected: sources: - serviceAccountToken: audience: my-buildbarn-instance expirationSeconds: 3600 path: buildbarn Assuming this is mounted at '/tokens', you could then specify in your buildbarn config: addMetadataJmespathExpression: { expression: ||| { "authorization": [std.format('bearer %s', files.token)] } |||, files: [ { key: "token", path: "/tokens/buildbarn", refreshInterval: "1800s", } ] }, This is quite useful for k8s service account tokens, as the maximum validity is often capped. Likewise this can also be used for Google service account id tokens, which also have a relatively short maximum validity.
1 parent b446105 commit add8296

62 files changed

Lines changed: 1263 additions & 266 deletions

Some content is hidden

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

cmd/bb_copy/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func main() {
4242
grpcClientFactory := grpc.NewBaseClientFactory(grpc.BaseClientDialer, nil, nil, nil)
4343

4444
blobAccessCreator := blobstore_configuration.NewCASBlobAccessCreator(
45+
dependenciesGroup,
4546
grpcClientFactory,
4647
int(configuration.MaximumMessageSizeBytes))
4748
source, err := blobstore_configuration.NewBlobAccessFromConfiguration(
@@ -62,7 +63,7 @@ func main() {
6263
configuration.Replicator,
6364
source.BlobAccess,
6465
sink,
65-
blobstore_configuration.NewCASBlobReplicatorCreator(grpcClientFactory),
66+
blobstore_configuration.NewCASBlobReplicatorCreator(dependenciesGroup, grpcClientFactory),
6667
)
6768
if err != nil {
6869
return util.StatusWrap(err, "Failed to create replicator")

cmd/bb_replicator/main.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@ func main() {
2727
if err := util.UnmarshalConfigurationFromFile(os.Args[1], &configuration); err != nil {
2828
return util.StatusWrapf(err, "Failed to read configuration from %s", os.Args[1])
2929
}
30-
lifecycleState, grpcClientFactory, err := global.ApplyConfiguration(configuration.Global)
30+
lifecycleState, grpcClientFactory, err := global.ApplyConfiguration(configuration.Global, dependenciesGroup)
3131
if err != nil {
3232
return util.StatusWrap(err, "Failed to apply global configuration options")
3333
}
3434

3535
blobAccessCreator := blobstore_configuration.NewCASBlobAccessCreator(
36+
dependenciesGroup,
3637
grpcClientFactory,
3738
int(configuration.MaximumMessageSizeBytes))
3839
source, err := blobstore_configuration.NewBlobAccessFromConfiguration(
@@ -53,7 +54,7 @@ func main() {
5354
configuration.Replicator,
5455
source.BlobAccess,
5556
sink,
56-
blobstore_configuration.NewCASBlobReplicatorCreator(grpcClientFactory),
57+
blobstore_configuration.NewCASBlobReplicatorCreator(dependenciesGroup, grpcClientFactory),
5758
)
5859
if err != nil {
5960
return util.StatusWrap(err, "Failed to create replicator")

cmd/bb_storage/main.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func main() {
3636
if err := util.UnmarshalConfigurationFromFile(os.Args[1], &configuration); err != nil {
3737
return util.StatusWrapf(err, "Failed to read configuration from %s", os.Args[1])
3838
}
39-
lifecycleState, grpcClientFactory, err := global.ApplyConfiguration(configuration.Global)
39+
lifecycleState, grpcClientFactory, err := global.ApplyConfiguration(configuration.Global, dependenciesGroup)
4040
if err != nil {
4141
return util.StatusWrap(err, "Failed to apply global configuration options")
4242
}
@@ -56,6 +56,7 @@ func main() {
5656
dependenciesGroup,
5757
configuration.ContentAddressableStorage,
5858
blobstore_configuration.NewCASBlobAccessCreator(
59+
dependenciesGroup,
5960
grpcClientFactory,
6061
int(configuration.MaximumMessageSizeBytes)),
6162
grpcClientFactory)
@@ -83,9 +84,11 @@ func main() {
8384
dependenciesGroup,
8485
configuration.ActionCache,
8586
blobstore_configuration.NewACBlobAccessCreator(
87+
dependenciesGroup,
8688
contentAddressableStorageInfo,
8789
grpcClientFactory,
88-
int(configuration.MaximumMessageSizeBytes)),
90+
int(configuration.MaximumMessageSizeBytes),
91+
),
8992
grpcClientFactory)
9093
if err != nil {
9194
return util.StatusWrap(err, "Failed to create Action Cache")
@@ -104,6 +107,7 @@ func main() {
104107
dependenciesGroup,
105108
configuration.IndirectContentAddressableStorage,
106109
blobstore_configuration.NewICASBlobAccessCreator(
110+
dependenciesGroup,
107111
grpcClientFactory,
108112
int(configuration.MaximumMessageSizeBytes)),
109113
grpcClientFactory)
@@ -120,6 +124,7 @@ func main() {
120124
dependenciesGroup,
121125
configuration.InitialSizeClassCache,
122126
blobstore_configuration.NewISCCBlobAccessCreator(
127+
dependenciesGroup,
123128
grpcClientFactory,
124129
int(configuration.MaximumMessageSizeBytes)),
125130
grpcClientFactory)
@@ -136,6 +141,7 @@ func main() {
136141
dependenciesGroup,
137142
configuration.FileSystemAccessCache,
138143
blobstore_configuration.NewFSACBlobAccessCreator(
144+
dependenciesGroup,
139145
grpcClientFactory,
140146
int(configuration.MaximumMessageSizeBytes)),
141147
grpcClientFactory)
@@ -158,11 +164,11 @@ func main() {
158164
// one or more schedulers specified in the configuration file.
159165
var buildQueue builder.BuildQueue
160166
if len(configuration.Schedulers) > 0 {
161-
baseBuildQueue, err := builder.NewDemultiplexingBuildQueueFromConfiguration(configuration.Schedulers, grpcClientFactory)
167+
baseBuildQueue, err := builder.NewDemultiplexingBuildQueueFromConfiguration(configuration.Schedulers, dependenciesGroup, grpcClientFactory)
162168
if err != nil {
163169
return err
164170
}
165-
executeAuthorizer, err := auth_configuration.DefaultAuthorizerFactory.NewAuthorizerFromConfiguration(configuration.GetExecuteAuthorizer(), grpcClientFactory)
171+
executeAuthorizer, err := auth_configuration.DefaultAuthorizerFactory.NewAuthorizerFromConfiguration(configuration.GetExecuteAuthorizer(), dependenciesGroup, grpcClientFactory)
166172
if err != nil {
167173
return util.StatusWrap(err, "Failed to create execute authorizer")
168174
}
@@ -240,11 +246,11 @@ func newNonScannableBlobAccess(dependenciesGroup program.Group, configuration *b
240246
return blobstore_configuration.BlobAccessInfo{}, nil, nil, nil, err
241247
}
242248

243-
getAuthorizer, err := auth_configuration.DefaultAuthorizerFactory.NewAuthorizerFromConfiguration(configuration.GetAuthorizer, grpcClientFactory)
249+
getAuthorizer, err := auth_configuration.DefaultAuthorizerFactory.NewAuthorizerFromConfiguration(configuration.GetAuthorizer, dependenciesGroup, grpcClientFactory)
244250
if err != nil {
245251
return blobstore_configuration.BlobAccessInfo{}, nil, nil, nil, util.StatusWrap(err, "Failed to create Get() authorizer")
246252
}
247-
putAuthorizer, err := auth_configuration.DefaultAuthorizerFactory.NewAuthorizerFromConfiguration(configuration.PutAuthorizer, grpcClientFactory)
253+
putAuthorizer, err := auth_configuration.DefaultAuthorizerFactory.NewAuthorizerFromConfiguration(configuration.PutAuthorizer, dependenciesGroup, grpcClientFactory)
248254
if err != nil {
249255
return blobstore_configuration.BlobAccessInfo{}, nil, nil, nil, util.StatusWrap(err, "Failed to create Put() authorizer")
250256
}
@@ -262,15 +268,15 @@ func newScannableBlobAccess(dependenciesGroup program.Group, configuration *bb_s
262268
return blobstore_configuration.BlobAccessInfo{}, nil, nil, err
263269
}
264270

265-
getAuthorizer, err := auth_configuration.DefaultAuthorizerFactory.NewAuthorizerFromConfiguration(configuration.GetAuthorizer, grpcClientFactory)
271+
getAuthorizer, err := auth_configuration.DefaultAuthorizerFactory.NewAuthorizerFromConfiguration(configuration.GetAuthorizer, dependenciesGroup, grpcClientFactory)
266272
if err != nil {
267273
return blobstore_configuration.BlobAccessInfo{}, nil, nil, util.StatusWrap(err, "Failed to create Get() authorizer")
268274
}
269-
putAuthorizer, err := auth_configuration.DefaultAuthorizerFactory.NewAuthorizerFromConfiguration(configuration.PutAuthorizer, grpcClientFactory)
275+
putAuthorizer, err := auth_configuration.DefaultAuthorizerFactory.NewAuthorizerFromConfiguration(configuration.PutAuthorizer, dependenciesGroup, grpcClientFactory)
270276
if err != nil {
271277
return blobstore_configuration.BlobAccessInfo{}, nil, nil, util.StatusWrap(err, "Failed to create Put() authorizer")
272278
}
273-
findMissingAuthorizer, err := auth_configuration.DefaultAuthorizerFactory.NewAuthorizerFromConfiguration(configuration.FindMissingAuthorizer, grpcClientFactory)
279+
findMissingAuthorizer, err := auth_configuration.DefaultAuthorizerFactory.NewAuthorizerFromConfiguration(configuration.FindMissingAuthorizer, dependenciesGroup, grpcClientFactory)
274280
if err != nil {
275281
return blobstore_configuration.BlobAccessInfo{}, nil, nil, util.StatusWrap(err, "Failed to create FindMissing() authorizer")
276282
}

internal/mock/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ go_library(
410410
"//pkg/digest",
411411
"//pkg/filesystem",
412412
"//pkg/filesystem/path",
413+
"//pkg/program",
413414
"//pkg/proto/blobstore/local",
414415
"//pkg/proto/configuration/grpc",
415416
"//pkg/util",

pkg/auth/BUILD.bazel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ go_library(
1818
"//pkg/clock",
1919
"//pkg/digest",
2020
"//pkg/eviction",
21+
"//pkg/jmespath",
2122
"//pkg/otel",
2223
"//pkg/proto/auth",
2324
"//pkg/util",
24-
"@com_github_jmespath_go_jmespath//:go-jmespath",
2525
"@io_opentelemetry_go_otel//attribute",
2626
"@org_golang_google_grpc//:grpc",
2727
"@org_golang_google_grpc//codes",
@@ -47,10 +47,10 @@ go_test(
4747
"//internal/mock",
4848
"//pkg/digest",
4949
"//pkg/eviction",
50+
"//pkg/jmespath",
5051
"//pkg/proto/auth",
5152
"//pkg/testutil",
5253
"//pkg/util",
53-
"@com_github_jmespath_go_jmespath//:go-jmespath",
5454
"@com_github_stretchr_testify//require",
5555
"@io_opentelemetry_go_otel//attribute",
5656
"@io_opentelemetry_go_proto_otlp//common/v1:common",

pkg/auth/configuration/BUILD.bazel

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ go_library(
1111
"//pkg/digest",
1212
"//pkg/eviction",
1313
"//pkg/grpc",
14+
"//pkg/jmespath",
15+
"//pkg/program",
1416
"//pkg/proto/configuration/auth",
1517
"//pkg/util",
16-
"@com_github_jmespath_go_jmespath//:go-jmespath",
1718
"@org_golang_google_grpc//codes",
1819
"@org_golang_google_grpc//status",
1920
"@org_golang_google_protobuf//encoding/protojson",

pkg/auth/configuration/authorizer_factory.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import (
66
"github.com/buildbarn/bb-storage/pkg/digest"
77
"github.com/buildbarn/bb-storage/pkg/eviction"
88
"github.com/buildbarn/bb-storage/pkg/grpc"
9+
"github.com/buildbarn/bb-storage/pkg/jmespath"
10+
"github.com/buildbarn/bb-storage/pkg/program"
911
pb "github.com/buildbarn/bb-storage/pkg/proto/configuration/auth"
1012
"github.com/buildbarn/bb-storage/pkg/util"
11-
"github.com/jmespath/go-jmespath"
1213

1314
"google.golang.org/grpc/codes"
1415
"google.golang.org/grpc/status"
@@ -20,7 +21,7 @@ import (
2021
type AuthorizerFactory interface {
2122
// NewAuthorizerFromConfiguration constructs an authorizer based on
2223
// options specified in a configuration message.
23-
NewAuthorizerFromConfiguration(configuration *pb.AuthorizerConfiguration, grpcClientFactory grpc.ClientFactory) (auth.Authorizer, error)
24+
NewAuthorizerFromConfiguration(configuration *pb.AuthorizerConfiguration, group program.Group, grpcClientFactory grpc.ClientFactory) (auth.Authorizer, error)
2425
}
2526

2627
// DefaultAuthorizerFactory constructs deduplicated authorizers based on
@@ -33,7 +34,7 @@ type BaseAuthorizerFactory struct{}
3334

3435
// NewAuthorizerFromConfiguration constructs an authorizer based on
3536
// options specified in a configuration message.
36-
func (f BaseAuthorizerFactory) NewAuthorizerFromConfiguration(config *pb.AuthorizerConfiguration, grpcClientFactory grpc.ClientFactory) (auth.Authorizer, error) {
37+
func (f BaseAuthorizerFactory) NewAuthorizerFromConfiguration(config *pb.AuthorizerConfiguration, group program.Group, grpcClientFactory grpc.ClientFactory) (auth.Authorizer, error) {
3738
if config == nil {
3839
return nil, status.Error(codes.InvalidArgument, "Authorizer configuration not specified")
3940
}
@@ -53,13 +54,13 @@ func (f BaseAuthorizerFactory) NewAuthorizerFromConfiguration(config *pb.Authori
5354
}
5455
return auth.NewStaticAuthorizer(trie.ContainsPrefix), nil
5556
case *pb.AuthorizerConfiguration_JmespathExpression:
56-
expression, err := jmespath.Compile(policy.JmespathExpression)
57+
expression, err := jmespath.NewExpressionFromConfiguration(policy.JmespathExpression, group, clock.SystemClock)
5758
if err != nil {
5859
return nil, util.StatusWrapWithCode(err, codes.InvalidArgument, "Failed to compile JMESPath expression")
5960
}
6061
return auth.NewJMESPathExpressionAuthorizer(expression), nil
6162
case *pb.AuthorizerConfiguration_Remote:
62-
grpcClient, err := grpcClientFactory.NewClientFromConfiguration(policy.Remote.Endpoint)
63+
grpcClient, err := grpcClientFactory.NewClientFromConfiguration(policy.Remote.Endpoint, group)
6364
if err != nil {
6465
return nil, util.StatusWrap(err, "Failed to create authorizer RPC client")
6566
}
@@ -96,14 +97,14 @@ func NewDeduplicatingAuthorizerFactory(base AuthorizerFactory) AuthorizerFactory
9697
}
9798

9899
// NewAuthorizerFromConfiguration creates an Authorizer based on the passed configuration.
99-
func (af *deduplicatingAuthorizerFactory) NewAuthorizerFromConfiguration(config *pb.AuthorizerConfiguration, grpcClientFactory grpc.ClientFactory) (auth.Authorizer, error) {
100+
func (af *deduplicatingAuthorizerFactory) NewAuthorizerFromConfiguration(config *pb.AuthorizerConfiguration, group program.Group, grpcClientFactory grpc.ClientFactory) (auth.Authorizer, error) {
100101
keyBytes, err := protojson.Marshal(config)
101102
key := string(keyBytes)
102103
if err != nil {
103104
return nil, err
104105
}
105106
if _, ok := af.known[key]; !ok {
106-
a, err := af.base.NewAuthorizerFromConfiguration(config, grpcClientFactory)
107+
a, err := af.base.NewAuthorizerFromConfiguration(config, group, grpcClientFactory)
107108
if err != nil {
108109
return nil, err
109110
}

pkg/auth/jmespath_expression_authorizer.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@ import (
44
"context"
55

66
"github.com/buildbarn/bb-storage/pkg/digest"
7-
"github.com/jmespath/go-jmespath"
7+
"github.com/buildbarn/bb-storage/pkg/jmespath"
88
)
99

1010
type jmespathExpressionAuthorizer struct {
11-
expression *jmespath.JMESPath
11+
expression *jmespath.Expression
1212
}
1313

1414
// NewJMESPathExpressionAuthorizer creates an Authorizer that evaluates
1515
// a JMESPath expression to make an authorization decision. The JMESpath
1616
// expression is called with a JSON object that includes both the REv2
1717
// instance name and authentication metadata.
18-
func NewJMESPathExpressionAuthorizer(expression *jmespath.JMESPath) Authorizer {
18+
func NewJMESPathExpressionAuthorizer(expression *jmespath.Expression) Authorizer {
1919
return &jmespathExpressionAuthorizer{
2020
expression: expression,
2121
}

pkg/auth/jmespath_expression_authorizer_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import (
66

77
"github.com/buildbarn/bb-storage/pkg/auth"
88
"github.com/buildbarn/bb-storage/pkg/digest"
9+
"github.com/buildbarn/bb-storage/pkg/jmespath"
910
auth_pb "github.com/buildbarn/bb-storage/pkg/proto/auth"
1011
"github.com/buildbarn/bb-storage/pkg/testutil"
1112
"github.com/buildbarn/bb-storage/pkg/util"
12-
"github.com/jmespath/go-jmespath"
1313
"github.com/stretchr/testify/require"
1414

1515
"google.golang.org/grpc/codes"

pkg/blobstore/configuration/ac_blob_access_creator.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/buildbarn/bb-storage/pkg/clock"
1010
"github.com/buildbarn/bb-storage/pkg/digest"
1111
"github.com/buildbarn/bb-storage/pkg/grpc"
12+
"github.com/buildbarn/bb-storage/pkg/program"
1213
pb "github.com/buildbarn/bb-storage/pkg/proto/configuration/blobstore"
1314
"github.com/buildbarn/bb-storage/pkg/util"
1415

@@ -33,16 +34,18 @@ type acBlobAccessCreator struct {
3334
contentAddressableStorage *BlobAccessInfo
3435
grpcClientFactory grpc.ClientFactory
3536
maximumMessageSizeBytes int
37+
terminationGroup program.Group
3638
}
3739

3840
// NewACBlobAccessCreator creates a BlobAccessCreator that can be
3941
// provided to NewBlobAccessFromConfiguration() to construct a
4042
// BlobAccess that is suitable for accessing the Action Cache.
41-
func NewACBlobAccessCreator(contentAddressableStorage *BlobAccessInfo, grpcClientFactory grpc.ClientFactory, maximumMessageSizeBytes int) BlobAccessCreator {
43+
func NewACBlobAccessCreator(terminationGroup program.Group, contentAddressableStorage *BlobAccessInfo, grpcClientFactory grpc.ClientFactory, maximumMessageSizeBytes int) BlobAccessCreator {
4244
return &acBlobAccessCreator{
4345
contentAddressableStorage: contentAddressableStorage,
4446
grpcClientFactory: grpcClientFactory,
4547
maximumMessageSizeBytes: maximumMessageSizeBytes,
48+
terminationGroup: terminationGroup,
4649
}
4750
}
4851

@@ -105,7 +108,7 @@ func (bac *acBlobAccessCreator) NewCustomBlobAccess(configuration *pb.BlobAccess
105108
DigestKeyFormat: base.DigestKeyFormat.Combine(bac.contentAddressableStorage.DigestKeyFormat),
106109
}, "completeness_checking", nil
107110
case *pb.BlobAccessConfiguration_Grpc:
108-
client, err := bac.grpcClientFactory.NewClientFromConfiguration(backend.Grpc)
111+
client, err := bac.grpcClientFactory.NewClientFromConfiguration(backend.Grpc, bac.terminationGroup)
109112
if err != nil {
110113
return BlobAccessInfo{}, "", err
111114
}

0 commit comments

Comments
 (0)