fix(deps): update github.com/containers/common digest to 3e93a76

Signed-off-by: Renovate Bot <bot@renovateapp.com>
This commit is contained in:
renovate[bot]
2023-05-06 11:14:08 +00:00
committed by GitHub
parent ace3cba5c1
commit 11d92ea376
228 changed files with 24071 additions and 1551 deletions

View File

@ -15,6 +15,7 @@
package name
import (
// nolint: depguard
_ "crypto/sha256" // Recommended by go-digest.
"strings"

124
vendor/github.com/google/trillian/client/admin.go generated vendored Normal file
View File

@ -0,0 +1,124 @@
// Copyright 2018 Google LLC. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package client
import (
"context"
"fmt"
"time"
"github.com/google/trillian"
"github.com/google/trillian/client/backoff"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"k8s.io/klog/v2"
)
// CreateAndInitTree uses the adminClient and logClient to create the tree
// described by req.
// If req describes a LOG tree, then this function will also call the InitLog
// function using logClient.
// Internally, the function will continue to retry failed requests until either
// the tree is created (and if necessary, initialised) successfully, or ctx is
// cancelled.
func CreateAndInitTree(
ctx context.Context,
req *trillian.CreateTreeRequest,
adminClient trillian.TrillianAdminClient,
logClient trillian.TrillianLogClient) (*trillian.Tree, error) {
b := &backoff.Backoff{
Min: 100 * time.Millisecond,
Max: 10 * time.Second,
Factor: 2,
Jitter: true,
}
var tree *trillian.Tree
err := b.Retry(ctx, func() error {
klog.Info("CreateTree...")
var err error
tree, err = adminClient.CreateTree(ctx, req)
switch code := status.Code(err); code {
case codes.Unavailable:
klog.Errorf("Admin server unavailable: %v", err)
return err
case codes.OK:
return nil
default:
klog.Errorf("failed to CreateTree(%+v): %T %v", req, err, err)
return err
}
})
if err != nil {
return nil, err
}
switch tree.TreeType {
case trillian.TreeType_LOG, trillian.TreeType_PREORDERED_LOG:
if err := InitLog(ctx, tree, logClient); err != nil {
return nil, err
}
default:
return nil, fmt.Errorf("don't know how or whether to initialise tree type %v", tree.TreeType)
}
return tree, nil
}
// InitLog initialises a freshly created Log tree.
func InitLog(ctx context.Context, tree *trillian.Tree, logClient trillian.TrillianLogClient) error {
if tree.TreeType != trillian.TreeType_LOG &&
tree.TreeType != trillian.TreeType_PREORDERED_LOG {
return fmt.Errorf("InitLog called with tree of type %v", tree.TreeType)
}
b := &backoff.Backoff{
Min: 100 * time.Millisecond,
Max: 10 * time.Second,
Factor: 2,
Jitter: true,
}
err := b.Retry(ctx, func() error {
klog.Infof("Initialising Log %v...", tree.TreeId)
req := &trillian.InitLogRequest{LogId: tree.TreeId}
resp, err := logClient.InitLog(ctx, req)
switch code := status.Code(err); code {
case codes.Unavailable:
klog.Errorf("Log server unavailable: %v", err)
return err
case codes.AlreadyExists:
klog.Warningf("Bizarrely, the just-created Log (%v) is already initialised!: %v", tree.TreeId, err)
return err
case codes.OK:
klog.Infof("Initialised Log (%v) with new SignedTreeHead:\n%+v",
tree.TreeId, resp.Created)
return nil
default:
klog.Errorf("failed to InitLog(%+v): %T %v", req, err, err)
return err
}
})
if err != nil {
return err
}
// Wait for log root to become available.
return b.Retry(ctx, func() error {
_, err := logClient.GetLatestSignedLogRoot(ctx,
&trillian.GetLatestSignedLogRootRequest{LogId: tree.TreeId})
return err
}, codes.FailedPrecondition)
}

View File

@ -0,0 +1,130 @@
// Copyright 2017 Google LLC. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package backoff allows retrying an operation with backoff.
package backoff
import (
"context"
"fmt"
"math/rand"
"time"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// RetriableError explicitly instructs Backoff to retry.
type RetriableError string
// Error returns string representation of the retriable error.
func (re RetriableError) Error() string {
return string(re)
}
// RetriableErrorf wraps a formatted string into a RetriableError.
func RetriableErrorf(format string, a ...interface{}) error {
return RetriableError(fmt.Sprintf(format, a...))
}
// Backoff specifies the parameters of the backoff algorithm. Works correctly
// if 0 < Min <= Max <= 2^62 (nanosec), and Factor >= 1.
type Backoff struct {
Min time.Duration // Duration of the first pause.
Max time.Duration // Max duration of a pause.
Factor float64 // The factor of duration increase between iterations.
Jitter bool // Add random noise to pauses.
delta time.Duration // Current pause duration relative to Min, no jitter.
}
// Duration returns the time to wait on current retry iteration. Every time
// Duration is called, the returned value will exponentially increase by Factor
// until Backoff.Max. If Jitter is enabled, will add an additional random value
// between 0 and the duration, so the result can at most double.
func (b *Backoff) Duration() time.Duration {
base := b.Min + b.delta
pause := base
if b.Jitter { // Add a number in the range [0, pause).
pause += time.Duration(rand.Int63n(int64(pause)))
}
nextPause := time.Duration(float64(base) * b.Factor)
if nextPause > b.Max || nextPause < b.Min { // Multiplication could overflow.
nextPause = b.Max
}
b.delta = nextPause - b.Min
return pause
}
// Reset sets the internal state back to first retry iteration.
func (b *Backoff) Reset() {
b.delta = 0
}
// Retry calls a function until it succeeds or the context is done.
// It will backoff if the function returns a retryable error.
// Once the context is done, retries will end and the most recent error will be returned.
// Backoff is not reset by this function.
func (b *Backoff) Retry(ctx context.Context, f func() error, retry ...codes.Code) error {
// If the context is already done, don't make any attempts to call f.
if ctx.Err() != nil {
return ctx.Err()
}
// Try calling f while the error is retryable and ctx is not done.
for {
if err := f(); !IsRetryable(err, retry...) {
return err
}
select {
case <-time.After(b.Duration()):
case <-ctx.Done():
return ctx.Err()
}
}
}
// IsRetryable returns false unless the error is explicitly retriable per
// https://godoc.org/google.golang.org/grpc/codes,
// or if the error codes is in retry. codes.OK is not retryable.
func IsRetryable(err error, retry ...codes.Code) bool {
code := status.Code(err)
switch code {
// Fast path.
case codes.OK:
return false
// Debatable cases:
case codes.DeadlineExceeded,
codes.ResourceExhausted: // Retry with backoff.
return true
// Errors that are explicitly retryable:
case codes.Unavailable, // Client can just retry the call.
codes.Aborted: // Client can retry the read-modify-write function.
return true
}
for _, c := range retry {
if code == c {
return true
}
}
// Don't retry for all other errors, unless it is a RetriableError.
_, ok := err.(RetriableError)
return ok
}

343
vendor/github.com/google/trillian/client/log_client.go generated vendored Normal file
View File

@ -0,0 +1,343 @@
// Copyright 2017 Google LLC. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package client verifies responses from the Trillian log.
package client
import (
"bytes"
"context"
"fmt"
"sort"
"sync"
"time"
"github.com/google/trillian"
"github.com/google/trillian/client/backoff"
"github.com/google/trillian/types"
"github.com/transparency-dev/merkle"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// LogClient represents a client for a given Trillian log instance.
type LogClient struct {
*LogVerifier
LogID int64
MinMergeDelay time.Duration
client trillian.TrillianLogClient
root types.LogRootV1
rootLock sync.Mutex
updateLock sync.Mutex
}
// New returns a new LogClient.
func New(logID int64, client trillian.TrillianLogClient, verifier *LogVerifier, root types.LogRootV1) *LogClient {
return &LogClient{
LogVerifier: verifier,
LogID: logID,
client: client,
root: root,
}
}
// NewFromTree creates a new LogClient given a tree config.
func NewFromTree(client trillian.TrillianLogClient, config *trillian.Tree, root types.LogRootV1) (*LogClient, error) {
verifier, err := NewLogVerifierFromTree(config)
if err != nil {
return nil, err
}
return New(config.GetTreeId(), client, verifier, root), nil
}
// AddLeaf adds leaf to the append only log.
// Blocks and continuously updates the trusted root until a successful inclusion proof
// can be retrieved.
func (c *LogClient) AddLeaf(ctx context.Context, data []byte) error {
if err := c.QueueLeaf(ctx, data); err != nil {
return fmt.Errorf("QueueLeaf(): %v", err)
}
if err := c.WaitForInclusion(ctx, data); err != nil {
return fmt.Errorf("WaitForInclusion(): %v", err)
}
return nil
}
// ListByIndex returns the requested leaves by index.
func (c *LogClient) ListByIndex(ctx context.Context, start, count int64) ([]*trillian.LogLeaf, error) {
resp, err := c.client.GetLeavesByRange(ctx,
&trillian.GetLeavesByRangeRequest{
LogId: c.LogID,
StartIndex: start,
Count: count,
})
if err != nil {
return nil, err
}
// Verify that we got back the requested leaves.
if len(resp.Leaves) < int(count) {
return nil, fmt.Errorf("len(Leaves)=%d, want %d", len(resp.Leaves), count)
}
for i, l := range resp.Leaves {
if want := start + int64(i); l.LeafIndex != want {
return nil, fmt.Errorf("Leaves[%d].LeafIndex=%d, want %d", i, l.LeafIndex, want)
}
}
return resp.Leaves, nil
}
// WaitForRootUpdate repeatedly fetches the latest root until there is an
// update, which it then applies, or until ctx times out.
func (c *LogClient) WaitForRootUpdate(ctx context.Context) (*types.LogRootV1, error) {
b := &backoff.Backoff{
Min: 100 * time.Millisecond,
Max: 10 * time.Second,
Factor: 2,
Jitter: true,
}
for {
newTrusted, err := c.UpdateRoot(ctx)
switch status.Code(err) {
case codes.OK:
if newTrusted != nil {
return newTrusted, nil
}
case codes.Unavailable, codes.NotFound, codes.FailedPrecondition:
// Retry.
default:
return nil, err
}
select {
case <-ctx.Done():
return nil, status.Errorf(codes.DeadlineExceeded, "%v", ctx.Err())
case <-time.After(b.Duration()):
}
}
}
// getAndVerifyLatestRoot fetches and verifies the latest root against a trusted root, seen in the past.
// Pass nil for trusted if this is the first time querying this log.
func (c *LogClient) getAndVerifyLatestRoot(ctx context.Context, trusted *types.LogRootV1) (*types.LogRootV1, error) {
resp, err := c.client.GetLatestSignedLogRoot(ctx,
&trillian.GetLatestSignedLogRootRequest{
LogId: c.LogID,
FirstTreeSize: int64(trusted.TreeSize),
})
if err != nil {
return nil, err
}
// TODO(gbelvin): Turn on root verification.
/*
logRoot, err := c.VerifyRoot(&types.LogRootV1{}, resp.GetSignedLogRoot(), nil)
if err != nil {
return nil, err
}
*/
// TODO(gbelvin): Remove this hack when all implementations store digital signatures.
var logRoot types.LogRootV1
if err := logRoot.UnmarshalBinary(resp.GetSignedLogRoot().LogRoot); err != nil {
return nil, err
}
if trusted.TreeSize > 0 &&
logRoot.TreeSize == trusted.TreeSize &&
bytes.Equal(logRoot.RootHash, trusted.RootHash) {
// Tree has not been updated.
return &logRoot, nil
}
// Verify root update if the tree / the latest signed log root isn't empty.
if logRoot.TreeSize > 0 {
if _, err := c.VerifyRoot(trusted, resp.GetSignedLogRoot(), resp.GetProof().GetHashes()); err != nil {
return nil, err
}
}
return &logRoot, nil
}
// GetRoot returns a copy of the latest trusted root.
func (c *LogClient) GetRoot() *types.LogRootV1 {
c.rootLock.Lock()
defer c.rootLock.Unlock()
// Copy the internal trusted root in order to prevent clients from modifying it.
ret := c.root
return &ret
}
// UpdateRoot retrieves the current SignedLogRoot, verifying it against roots this client has
// seen in the past, and updating the currently trusted root if the new root verifies, and is
// newer than the currently trusted root.
func (c *LogClient) UpdateRoot(ctx context.Context) (*types.LogRootV1, error) {
// Only one root update should be running at any point in time, because
// the update involves a consistency proof from the old value, and if the
// old value could change along the way (in another goroutine) then the
// result could be inconsistent.
//
// For example, if the current root is A and two root updates A->B and A->C
// happen in parallel, then we might end up with the transitions A->B->C:
// cur := A cur := A
// getRoot() => B getRoot() => C
// proof(A->B) ok proof(A->C) ok
// c.root = B
// c.root = C
// and the last step (B->C) has no proof and so could hide a forked tree.
c.updateLock.Lock()
defer c.updateLock.Unlock()
currentlyTrusted := c.GetRoot()
newTrusted, err := c.getAndVerifyLatestRoot(ctx, currentlyTrusted)
if err != nil {
return nil, err
}
// Lock "rootLock" for the "root" update.
c.rootLock.Lock()
defer c.rootLock.Unlock()
if newTrusted.TimestampNanos > currentlyTrusted.TimestampNanos &&
newTrusted.TreeSize >= currentlyTrusted.TreeSize {
// Take a copy of the new trusted root in order to prevent clients from modifying it.
c.root = *newTrusted
return newTrusted, nil
}
return nil, nil
}
// WaitForInclusion blocks until the requested data has been verified with an
// inclusion proof.
//
// It will continuously update the root to the latest one available until the
// data is found, or an error is returned.
//
// It is best to call this method with a context that will timeout to avoid
// waiting forever.
func (c *LogClient) WaitForInclusion(ctx context.Context, data []byte) error {
leaf := prepareLeaf(c.hasher, data)
// If a minimum merge delay has been configured, wait at least that long before
// starting to poll
if c.MinMergeDelay > 0 {
select {
case <-ctx.Done():
return status.Errorf(codes.DeadlineExceeded, "%v", ctx.Err())
case <-time.After(c.MinMergeDelay):
}
}
var root *types.LogRootV1
for {
root = c.GetRoot()
// It is illegal to ask for an inclusion proof with TreeSize = 0.
if root.TreeSize >= 1 {
ok, err := c.getAndVerifyInclusionProof(ctx, leaf.MerkleLeafHash, root)
if err != nil && status.Code(err) != codes.NotFound {
return err
} else if ok {
return nil
}
}
// If not found or tree is empty, wait for a root update before retrying again.
if _, err := c.WaitForRootUpdate(ctx); err != nil {
return err
}
// Retry
}
}
func (c *LogClient) getAndVerifyInclusionProof(ctx context.Context, leafHash []byte, sth *types.LogRootV1) (bool, error) {
resp, err := c.client.GetInclusionProofByHash(ctx,
&trillian.GetInclusionProofByHashRequest{
LogId: c.LogID,
LeafHash: leafHash,
TreeSize: int64(sth.TreeSize),
})
if err != nil {
return false, err
}
if len(resp.Proof) < 1 {
return false, nil
}
for _, proof := range resp.Proof {
if err := c.VerifyInclusionByHash(sth, leafHash, proof); err != nil {
return false, fmt.Errorf("VerifyInclusionByHash(): %v", err)
}
}
return true, nil
}
// AddSequencedLeaves adds any number of pre-sequenced leaves to the log.
// Indexes must be contiguous.
func (c *LogClient) AddSequencedLeaves(ctx context.Context, dataByIndex map[int64][]byte) error {
if len(dataByIndex) == 0 {
return nil
}
leaves := make([]*trillian.LogLeaf, 0, len(dataByIndex))
indexes := make([]int64, 0, len(dataByIndex))
for index := range dataByIndex {
indexes = append(indexes, index)
}
sort.Slice(indexes, func(a, b int) bool { return indexes[a] < indexes[b] })
for i, index := range indexes {
// Check index continuity.
if want := indexes[0] + int64(i); index != want {
return fmt.Errorf("missing index in contiugous index range. got: %v, want: %v", index, want)
}
leaf := prepareLeaf(c.hasher, dataByIndex[index])
leaf.LeafIndex = index
leaves = append(leaves, leaf)
}
resp, err := c.client.AddSequencedLeaves(ctx, &trillian.AddSequencedLeavesRequest{
LogId: c.LogID,
Leaves: leaves,
})
for _, leaf := range resp.GetResults() {
if s := status.FromProto(leaf.GetStatus()); s.Code() != codes.OK && s.Code() != codes.AlreadyExists {
return status.Errorf(s.Code(), "unexpected fail status in AddSequencedLeaves: %+v, err: %v", leaf, s.Message())
}
}
return err
}
// QueueLeaf adds a leaf to a Trillian log without blocking.
// AlreadyExists is considered a success case by this function.
func (c *LogClient) QueueLeaf(ctx context.Context, data []byte) error {
leaf := prepareLeaf(c.hasher, data)
_, err := c.client.QueueLeaf(ctx, &trillian.QueueLeafRequest{
LogId: c.LogID,
Leaf: leaf,
})
return err
}
// prepareLeaf returns a trillian.LogLeaf prepopulated with leaf data and hash.
func prepareLeaf(hasher merkle.LogHasher, data []byte) *trillian.LogLeaf {
leafHash := hasher.HashLeaf(data)
return &trillian.LogLeaf{
LeafValue: data,
MerkleLeafHash: leafHash,
}
}

View File

@ -0,0 +1,91 @@
// Copyright 2017 Google LLC. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package client
import (
"errors"
"fmt"
"github.com/google/trillian"
"github.com/google/trillian/types"
"github.com/transparency-dev/merkle"
"github.com/transparency-dev/merkle/proof"
"github.com/transparency-dev/merkle/rfc6962"
)
// LogVerifier allows verification of output from Trillian Logs, both regular
// and pre-ordered; it is safe for concurrent use (as its contents are fixed
// after construction).
type LogVerifier struct {
// hasher is the hash strategy used to compute nodes in the Merkle tree.
hasher merkle.LogHasher
}
// NewLogVerifier returns an object that can verify output from Trillian Logs.
func NewLogVerifier(hasher merkle.LogHasher) *LogVerifier {
return &LogVerifier{hasher: hasher}
}
// NewLogVerifierFromTree creates a new LogVerifier using the algorithms
// specified by a Trillian Tree object.
func NewLogVerifierFromTree(config *trillian.Tree) (*LogVerifier, error) {
if config == nil {
return nil, errors.New("client: NewLogVerifierFromTree(): nil config")
}
log, pLog := trillian.TreeType_LOG, trillian.TreeType_PREORDERED_LOG
if got := config.TreeType; got != log && got != pLog {
return nil, fmt.Errorf("client: NewLogVerifierFromTree(): TreeType: %v, want %v or %v", got, log, pLog)
}
return NewLogVerifier(rfc6962.DefaultHasher), nil
}
// VerifyRoot verifies that newRoot is a valid append-only operation from
// trusted. If trusted.TreeSize is zero, a consistency proof is not needed.
func (c *LogVerifier) VerifyRoot(trusted *types.LogRootV1, newRoot *trillian.SignedLogRoot, consistency [][]byte) (*types.LogRootV1, error) {
if trusted == nil {
return nil, fmt.Errorf("VerifyRoot() error: trusted == nil")
}
if newRoot == nil {
return nil, fmt.Errorf("VerifyRoot() error: newRoot == nil")
}
var r types.LogRootV1
if err := r.UnmarshalBinary(newRoot.LogRoot); err != nil {
return nil, err
}
// Implicitly trust the first root we get.
if trusted.TreeSize != 0 {
// Verify consistency proof.
if err := proof.VerifyConsistency(c.hasher, trusted.TreeSize, r.TreeSize, consistency, trusted.RootHash, r.RootHash); err != nil {
return nil, fmt.Errorf("failed to verify consistency proof from %d->%d %x->%x: %v", trusted.TreeSize, r.TreeSize, trusted.RootHash, r.RootHash, err)
}
}
return &r, nil
}
// VerifyInclusionByHash verifies that the inclusion proof for the given Merkle leafHash
// matches the given trusted root.
func (c *LogVerifier) VerifyInclusionByHash(trusted *types.LogRootV1, leafHash []byte, pf *trillian.Proof) error {
if trusted == nil {
return fmt.Errorf("VerifyInclusionByHash() error: trusted == nil")
}
if pf == nil {
return fmt.Errorf("VerifyInclusionByHash() error: proof == nil")
}
return proof.VerifyInclusion(c.hasher, uint64(pf.LeafIndex), trusted.TreeSize, leafHash, pf.Hashes, trusted.RootHash)
}