Skip to content

Commit f3ce796

Browse files
author
dlorenc
authored
Add support for storing in-toto Attestations outside the log. (sigstore#321)
This adds an "Attestation" method to the entry interface. Entries can return an attestation that they would like to store. The attestations are currently stored in GCS, but it supports any blob store. The feature is turned off with a flag, and we can set a max size as well. Signed-off-by: Dan Lorenc <dlorenc@google.com>
1 parent dd0ffbe commit f3ce796

File tree

25 files changed

+195
-68
lines changed

25 files changed

+195
-68
lines changed

cmd/rekor-cli/app/pflags.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ func CreateIntotoFromPFlags() (models.ProposedEntry, error) {
235235
re := intoto_v001.V001Entry{
236236
IntotoObj: models.IntotoV001Schema{
237237
Content: &models.IntotoV001SchemaContent{
238-
Envelope: swag.String(string(b)),
238+
Envelope: string(b),
239239
},
240240
PublicKey: &kb,
241241
},

cmd/rekor-server/app/root.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ func init() {
6969
rootCmd.PersistentFlags().String("redis_server.address", "127.0.0.1", "Redis server address")
7070
rootCmd.PersistentFlags().Uint16("redis_server.port", 6379, "Redis server port")
7171

72+
rootCmd.PersistentFlags().Bool("enable_attestation_storage", false, "enables rich attestation storage")
73+
rootCmd.PersistentFlags().String("attestation_storage_bucket", "", "url for attestation storage bucket")
74+
rootCmd.PersistentFlags().Int("max_attestation_size", 100*1024, "max size for attestation storage, in bytes")
75+
7276
if err := viper.BindPFlags(rootCmd.PersistentFlags()); err != nil {
7377
log.Logger.Fatal(err)
7478
}

docker-compose.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,13 @@ services:
8787
"--redis_server.port=6379",
8888
"--rekor_server.address=0.0.0.0",
8989
"--rekor_server.signer=memory",
90+
"--enable_attestation_storage",
91+
"--attestation_storage_bucket=file:///var/run/attestations",
9092
# Uncomment this for production logging
9193
# "--log_type=prod",
9294
]
95+
volumes:
96+
- "/var/run/attestations:/var/run/attestations"
9397
restart: always # keep the server running
9498
ports:
9599
- "3000:3000"

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ require (
1717
github.com/go-openapi/swag v0.19.15
1818
github.com/go-openapi/validate v0.20.2
1919
github.com/go-playground/validator v9.31.0+incompatible
20+
github.com/google/go-cmp v0.5.5
2021
github.com/google/rpmpack v0.0.0-20210107155803-d6befbf05148
2122
github.com/google/trillian v1.3.14-0.20210413093047-5e12fb368c8f
2223
github.com/in-toto/in-toto-golang v0.1.1-0.20210528150343-f7dc21abaccf

pkg/api/api.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"github.com/sigstore/rekor/pkg/log"
3535
pki "github.com/sigstore/rekor/pkg/pki/x509"
3636
"github.com/sigstore/rekor/pkg/signer"
37+
"github.com/sigstore/rekor/pkg/storage"
3738
"github.com/sigstore/sigstore/pkg/signature"
3839
)
3940

@@ -146,8 +147,9 @@ func NewAPI() (*API, error) {
146147
}
147148

148149
var (
149-
api *API
150-
redisClient radix.Client
150+
api *API
151+
redisClient radix.Client
152+
storageClient storage.AttestationStorage
151153
)
152154

153155
func ConfigureAPI() {
@@ -163,4 +165,11 @@ func ConfigureAPI() {
163165
log.Logger.Panic(err)
164166
}
165167
}
168+
169+
if viper.GetBool("enable_attestation_storage") {
170+
storageClient, err = storage.NewAttestationStorage()
171+
if err != nil {
172+
log.Logger.Panic(err)
173+
}
174+
}
166175
}

pkg/api/entries.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,20 @@ func CreateLogEntryHandler(params entries.CreateLogEntryParams) middleware.Respo
160160
}()
161161
}
162162

163+
if viper.GetBool("enable_attestation_storage") {
164+
165+
go func() {
166+
typ, attestation := entry.Attestation()
167+
if typ == "" {
168+
log.RequestIDLogger(params.HTTPRequest).Infof("no attestation for %s", uuid)
169+
return
170+
}
171+
if err := storeAttestation(context.Background(), uuid, typ, attestation); err != nil {
172+
log.RequestIDLogger(params.HTTPRequest).Errorf("error storing attestation: %s", err)
173+
}
174+
}()
175+
}
176+
163177
payload, err := logEntryAnon.MarshalBinary()
164178
if err != nil {
165179
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("signing error: %v", err), signingError)

pkg/api/error.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,10 @@ func handleRekorAPIError(params interface{}, code int, err error, message string
8989
return entries.NewGetLogEntryByUUIDDefault(code).WithPayload(errorMsg(message, code))
9090
}
9191
case entries.CreateLogEntryParams:
92-
logMsg(params.HTTPRequest)
9392
switch code {
93+
// We treat "duplicate entry" as an error, but it's not really an error, so we don't need to log it as one.
9494
case http.StatusBadRequest:
95+
logMsg(params.HTTPRequest)
9596
return entries.NewCreateLogEntryBadRequest().WithPayload(errorMsg(message, code))
9697
case http.StatusConflict:
9798
resp := entries.NewCreateLogEntryConflict().WithPayload(errorMsg(message, code))

pkg/api/index.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,7 @@ func SearchIndexNotImplementedHandler(params index.SearchIndexParams) middleware
9292
func addToIndex(ctx context.Context, key, value string) error {
9393
return redisClient.Do(ctx, radix.Cmd(nil, "LPUSH", key, value))
9494
}
95+
96+
func storeAttestation(ctx context.Context, uuid, attestationType string, attestation []byte) error {
97+
return storageClient.StoreAttestation(ctx, uuid, attestationType, attestation)
98+
}

pkg/generated/models/intoto_v001_schema.go

Lines changed: 1 addition & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/generated/restapi/embedded_spec.go

Lines changed: 0 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)