Skip to content

Commit 088ff91

Browse files
committed
Create separate binaries for each backend
1 parent cd2c13b commit 088ff91

File tree

19 files changed

+779
-377
lines changed

19 files changed

+779
-377
lines changed

Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
FROM --platform=$BUILDPLATFORM golang:1.25.3@sha256:6d4e5e74f47db00f7f24da5f53c1b4198ae46862a47395e30477365458347bf2 AS builder
1717
ARG TARGETOS
1818
ARG TARGETARCH
19+
ARG CLOUD_PROVIDER=gcp
1920
ENV APP_ROOT=/opt/app-root
2021
ENV GOPATH=$APP_ROOT
2122

@@ -30,9 +31,9 @@ ADD ./internal/ $APP_ROOT/src/internal/
3031

3132
ARG SERVER_LDFLAGS
3233
# Build server for deployment
33-
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} CGO_ENABLED=0 go build -ldflags "${SERVER_LDFLAGS}" ./cmd/rekor-server
34+
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} CGO_ENABLED=0 go build -ldflags "${SERVER_LDFLAGS}" -o rekor-server ./cmd/rekor-server-${CLOUD_PROVIDER}
3435
# Build server for debugger
35-
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} CGO_ENABLED=0 go build -gcflags "all=-N -l" -ldflags "${SERVER_LDFLAGS}" -o rekor-server_debug ./cmd/rekor-server
36+
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} CGO_ENABLED=0 go build -gcflags "all=-N -l" -ldflags "${SERVER_LDFLAGS}" -o rekor-server_debug ./cmd/rekor-server-${CLOUD_PROVIDER}
3637

3738
# Multi-stage deployment build
3839
FROM golang:1.25.3@sha256:6d4e5e74f47db00f7f24da5f53c1b4198ae46862a47395e30477365458347bf2 AS deploy

Dockerfile.release

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
FROM --platform=$BUILDPLATFORM golang:1.25.3-bookworm@sha256:4f43b271f9673eb7bd0cb3a49cc17b08d8d6ee110277e26dbacc93c43a5a7793 AS builder
1818
ARG TARGETOS
1919
ARG TARGETARCH
20+
ARG CLOUD_PROVIDER=gcp
2021
ENV APP_ROOT=/opt/app-root
2122
ENV GOPATH=$APP_ROOT
2223

@@ -31,7 +32,7 @@ ADD ./internal/ $APP_ROOT/src/internal/
3132

3233
ARG SERVER_LDFLAGS
3334
# Build server for deployment. Build without cgo since distroless/static-debian12 doesn't include lib/cgo
34-
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} CGO_ENABLED=0 go build -ldflags "${SERVER_LDFLAGS}" ./cmd/rekor-server
35+
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} CGO_ENABLED=0 go build -ldflags "${SERVER_LDFLAGS}" -o rekor-server ./cmd/rekor-server-${CLOUD_PROVIDER}
3536

3637
# Multi-stage deployment build
3738
FROM gcr.io/distroless/static-debian12:nonroot@sha256:e8a4044e0b4ae4257efa45fc026c0bc30ad320d43bd4c1a7d5271bd241e386d0 AS deploy

Makefile

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
.PHONY: all test clean lint gosec ko-local tools ldflags
1717

18-
all: protos rekor-server
18+
all: protos rekor-server-gcp rekor-server-aws
1919

2020
GIT_VERSION ?= $(shell git describe --tags --always --dirty)
2121
GIT_HASH ?= $(shell git rev-parse HEAD)
@@ -73,8 +73,15 @@ lint:
7373
gosec: ## Run gosec security scanner
7474
$(GOBIN)/gosec ./...
7575

76-
rekor-server: $(SRC) $(PROTO_SRC)
77-
CGO_ENABLED=0 go build -trimpath -ldflags "$(SERVER_LDFLAGS)" -o rekor-server ./cmd/rekor-server
76+
rekor-server-gcp: $(SRC) $(PROTO_SRC)
77+
CGO_ENABLED=0 go build -trimpath -tags gcp -ldflags "$(SERVER_LDFLAGS)" -o rekor-server-gcp ./cmd/rekor-server-gcp
78+
79+
rekor-server-aws: $(SRC) $(PROTO_SRC)
80+
CGO_ENABLED=0 go build -trimpath -tags aws -ldflags "$(SERVER_LDFLAGS)" -o rekor-server-aws ./cmd/rekor-server-aws
81+
82+
# Legacy target for backwards compatibility - builds GCP version
83+
rekor-server: rekor-server-gcp
84+
cp rekor-server-gcp rekor-server
7885

7986
ldflags: ## Print ldflags
8087
@echo $(SERVER_LDFLAGS)
@@ -86,7 +93,8 @@ ko-local: ## Build container images locally using ko
8693
KO_DOCKER_REPO=ko.local LDFLAGS="$(SERVER_LDFLAGS)" GIT_HASH=$(GIT_HASH) GIT_VERSION=$(GIT_VERSION) \
8794
ko publish --base-import-paths \
8895
--tags $(GIT_VERSION) --tags $(GIT_HASH) --image-refs rekorImagerefs \
89-
github.com/sigstore/rekor-tiles/v2/cmd/rekor-server
96+
github.com/sigstore/rekor-tiles/v2/cmd/rekor-server-gcp \
97+
github.com/sigstore/rekor-tiles/v2/cmd/rekor-server-aws
9098

9199
# generate Go protobuf code
92100
protos:
@@ -106,7 +114,7 @@ clean: ## Remove built binaries and artifacts
106114
rm -rf pkg/generated/protobuf/*
107115
rm -rf dist
108116
rm -rf hack/tools/bin
109-
rm -rf rekor-server
117+
rm -rf rekor-server rekor-server-gcp rekor-server-aws
110118

111119
##################
112120
# help

README.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,19 @@ to report them.
6060

6161
## Storage Backends
6262

63-
Rekor v2 supports multiple storage backends for flexibility in deployment:
63+
Rekor v2 supports multiple storage backends. To avoid binary bloat from unused dependencies, separate binaries for each backend are provided:
64+
65+
- `rekor-server-gcp`: GCP-specific binary (includes only Google Cloud dependencies)
66+
- `rekor-server-aws`: AWS-specific binary (includes only AWS dependencies)
6467

6568
### Google Cloud Platform (GCP)
69+
- **Binary**: `rekor-server-gcp`
6670
- **Object Storage**: Google Cloud Storage (GCS)
6771
- **Database**: Cloud Spanner
6872
- **Use case**: Preferred for global deployments requiring strong consistency and automatic scaling
6973

7074
### Amazon Web Services (AWS)
75+
- **Binary**: `rekor-server-aws`
7176
- **Object Storage**: Amazon S3
7277
- **Database**: Aurora MySQL (or RDS MySQL)
7378
- **Use case**: Cost-effective option for regional deployments with MySQL compatibility
@@ -93,7 +98,7 @@ When deploying your own instance, configure the storage backend using command-li
9398

9499
**GCP Backend:**
95100
```bash
96-
rekor-server serve \
101+
rekor-server-gcp serve \
97102
--hostname=your-hostname \
98103
--gcp-bucket=your-gcs-bucket \
99104
--gcp-spanner=projects/PROJECT/instances/INSTANCE/databases/DATABASE \
@@ -102,7 +107,7 @@ rekor-server serve \
102107

103108
**AWS Backend:**
104109
```bash
105-
rekor-server serve \
110+
rekor-server-aws serve \
106111
--hostname=your-hostname \
107112
--aws-bucket=your-s3-bucket \
108113
--aws-mysql-dsn="user:password@tcp(host:3306)/database?parseTime=true" \
@@ -129,7 +134,7 @@ Optional flags for both backends:
129134
- `--checkpoint-interval`: Frequency of checkpoint publishing (default: 30s)
130135
- `--batch-max-size`: Maximum entries per batch (default: 1024)
131136

132-
See `rekor-server serve --help` for all available options.
137+
See `rekor-server-gcp serve --help` or `rekor-server-aws serve --help` for all available options.
133138

134139
### Making a request
135140

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//
2+
// Copyright 2025 The Sigstore Authors.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package app
17+
18+
import (
19+
"crypto"
20+
"fmt"
21+
"log/slog"
22+
"os"
23+
24+
"github.com/spf13/cobra"
25+
"github.com/spf13/viper"
26+
27+
"github.com/sigstore/rekor-tiles/v2/internal/signerverifier"
28+
"github.com/sigstore/rekor-tiles/v2/internal/tessera"
29+
)
30+
31+
// AWSBackend implements the BackendConfig interface for AWS
32+
type AWSBackend struct{}
33+
34+
func (a *AWSBackend) Name() string {
35+
return "aws"
36+
}
37+
38+
func (a *AWSBackend) Description() string {
39+
return "Amazon Web Services"
40+
}
41+
42+
func (a *AWSBackend) SetupLogger(logLevel slog.Level) *slog.Logger {
43+
return slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: logLevel}))
44+
}
45+
46+
func (a *AWSBackend) RegisterFlags(cmd *cobra.Command) {
47+
// AWS-specific storage configs
48+
cmd.Flags().String("aws-bucket", "", "S3 bucket for tile and checkpoint storage")
49+
cmd.Flags().String("aws-mysql-dsn", "", "MySQL DSN for Aurora/RDS (e.g., user:pass@tcp(host:3306)/dbname)")
50+
51+
// AWS KMS configs
52+
cmd.Flags().String("signer-kmskey", "", "URI of the KMS key, in the form of awskms://keyname")
53+
cmd.Flags().String("signer-tink-kek-uri", "", "encryption key for decrypting Tink keyset. Valid options are [aws-kms://keyname]")
54+
}
55+
56+
func (a *AWSBackend) GetKMSSignerOptions() ([]signerverifier.Option, error) {
57+
kmshash := viper.GetString("signer-kmshash")
58+
hashAlg, ok := hashAlgMap[kmshash]
59+
if !ok {
60+
return nil, fmt.Errorf("invalid hash algorithm for --signer-kmshash: %s", kmshash)
61+
}
62+
// AWS KMS doesn't need the same RPC options as GCP
63+
return []signerverifier.Option{signerverifier.WithKMS(viper.GetString("signer-kmskey"), hashAlg, nil)}, nil
64+
}
65+
66+
func (a *AWSBackend) GetDriverConfig() (tessera.DriverConfiguration, error) {
67+
return tessera.DriverConfiguration{
68+
Hostname: viper.GetString("hostname"),
69+
AWSBucket: viper.GetString("aws-bucket"),
70+
AWSMySQLDSN: viper.GetString("aws-mysql-dsn"),
71+
PersistentAntispam: viper.GetBool("persistent-antispam"),
72+
ASMaxBatchSize: viper.GetUint("antispam-max-batch-size"),
73+
ASPushbackThreshold: viper.GetUint("antispam-pushback-threshold"),
74+
}, nil
75+
}
76+
77+
var hashAlgMap = map[string]crypto.Hash{
78+
"sha256": crypto.SHA256,
79+
"sha384": crypto.SHA384,
80+
"sha512": crypto.SHA512,
81+
}
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@
1515

1616
package main
1717

18-
import "github.com/sigstore/rekor-tiles/v2/cmd/rekor-server/app"
18+
import (
19+
sharedapp "github.com/sigstore/rekor-tiles/v2/cmd/rekor-server/app"
20+
"github.com/sigstore/rekor-tiles/v2/cmd/rekor-server-aws/app"
21+
)
1922

2023
func main() {
21-
app.Execute()
24+
sharedapp.Execute(&app.AWSBackend{})
2225
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//
2+
// Copyright 2025 The Sigstore Authors.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package app
17+
18+
import (
19+
"crypto"
20+
"fmt"
21+
"log/slog"
22+
"time"
23+
24+
clog "github.com/chainguard-dev/clog/gcp"
25+
grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
26+
"github.com/spf13/cobra"
27+
"github.com/spf13/viper"
28+
"google.golang.org/api/option"
29+
"google.golang.org/grpc"
30+
31+
"github.com/sigstore/rekor-tiles/v2/internal/signerverifier"
32+
"github.com/sigstore/rekor-tiles/v2/internal/tessera"
33+
"github.com/sigstore/sigstore/pkg/signature"
34+
"github.com/sigstore/sigstore/pkg/signature/kms/gcp"
35+
)
36+
37+
// GCPBackend implements the BackendConfig interface for GCP
38+
type GCPBackend struct{}
39+
40+
func (g *GCPBackend) Name() string {
41+
return "gcp"
42+
}
43+
44+
func (g *GCPBackend) Description() string {
45+
return "Google Cloud Platform"
46+
}
47+
48+
func (g *GCPBackend) SetupLogger(logLevel slog.Level) *slog.Logger {
49+
return slog.New(clog.NewHandler(logLevel))
50+
}
51+
52+
func (g *GCPBackend) RegisterFlags(cmd *cobra.Command) {
53+
// GCP-specific storage configs
54+
cmd.Flags().String("gcp-bucket", "", "GCS bucket for tile and checkpoint storage")
55+
cmd.Flags().String("gcp-spanner", "", "Spanner database URI")
56+
57+
// GCP KMS configs
58+
cmd.Flags().String("signer-kmskey", "", "URI of the KMS key, in the form of gcpkms://keyname")
59+
cmd.Flags().String("signer-tink-kek-uri", "", "encryption key for decrypting Tink keyset. Valid options are [gcp-kms://keyname]")
60+
cmd.Flags().Uint("gcp-kms-retries", 0, "number of retries for GCP KMS requests")
61+
cmd.Flags().Uint32("gcp-kms-timeout", 0, "sets the RPC timeout per call for GCP KMS requests in seconds, defaults to 0 (no timeout)")
62+
}
63+
64+
func (g *GCPBackend) GetKMSSignerOptions() ([]signerverifier.Option, error) {
65+
kmshash := viper.GetString("signer-kmshash")
66+
hashAlg, ok := hashAlgMap[kmshash]
67+
if !ok {
68+
return nil, fmt.Errorf("invalid hash algorithm for --signer-kmshash: %s", kmshash)
69+
}
70+
// initialize optional RPC options for GCP KMS
71+
rpcOpts := make([]signature.RPCOption, 0)
72+
callOpts := []grpc_retry.CallOption{grpc_retry.WithMax(viper.GetUint("gcp-kms-retries")), grpc_retry.WithPerRetryTimeout(time.Duration(viper.GetUint32("gcp-kms-timeout")) * time.Second)}
73+
rpcOpts = append(rpcOpts, gcp.WithGoogleAPIClientOption(option.WithGRPCDialOption(grpc.WithUnaryInterceptor(grpc_retry.UnaryClientInterceptor(callOpts...)))))
74+
75+
return []signerverifier.Option{signerverifier.WithKMS(viper.GetString("signer-kmskey"), hashAlg, rpcOpts)}, nil
76+
}
77+
78+
func (g *GCPBackend) GetDriverConfig() (tessera.DriverConfiguration, error) {
79+
return tessera.DriverConfiguration{
80+
Hostname: viper.GetString("hostname"),
81+
GCPBucket: viper.GetString("gcp-bucket"),
82+
GCPSpannerDB: viper.GetString("gcp-spanner"),
83+
PersistentAntispam: viper.GetBool("persistent-antispam"),
84+
ASMaxBatchSize: viper.GetUint("antispam-max-batch-size"),
85+
ASPushbackThreshold: viper.GetUint("antispam-pushback-threshold"),
86+
}, nil
87+
}
88+
89+
var hashAlgMap = map[string]crypto.Hash{
90+
"sha256": crypto.SHA256,
91+
"sha384": crypto.SHA384,
92+
"sha512": crypto.SHA512,
93+
}

cmd/rekor-server-gcp/main.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//
2+
// Copyright 2025 The Sigstore Authors.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package main
17+
18+
import (
19+
sharedapp "github.com/sigstore/rekor-tiles/v2/cmd/rekor-server/app"
20+
"github.com/sigstore/rekor-tiles/v2/cmd/rekor-server-gcp/app"
21+
)
22+
23+
func main() {
24+
sharedapp.Execute(&app.GCPBackend{})
25+
}

0 commit comments

Comments
 (0)