Files
Ramon Petgrave fe539a2bde fix: use sigstore/pkg/fulcioroots to lessen deps (#746)
We've long had the problem that slsa-verifier has too many dependencies.

This PR replaces `"github.com/sigstore/cosign/v2/cmd/cosign/cli/fulcio"`
with `"github.com/sigstore/sigstore/pkg/fulcioroots"`,
removing lot's of unneeded transitive dependencies like
`"github.com/aws/aws-sdk-go-v2"` and
`"github.com/Azure/go-autorest/autorest"` from our `go.mod`.

## Investigation

At
[deps.dep](https://deps.dev/go/github.com%2Fslsa-framework%2Fslsa-verifier%2Fv2/v2.4.1/dependencies/graph?filter=aws),
we can see that the indirect dependencies of `aws/aws-sdk-go-v2` come
from `cosign/cosign`.

<img width="1110" alt="image"
src="https://github.com/slsa-framework/slsa-verifier/assets/32398091/3de1adf4-29ac-4bec-a511-0ae191c3141c">

That's a good start, but this gives us only module-wide dependencies,
not package-level dependencies. We can instead use `go mod why <pkg>` to
get the package-level dependency chain.

Now we know that it's our `gha` package that imports a fulcio package,
which imports an aws package.

```
➜  slsa-verifier git:(main) ✗ go mod why github.com/aws/aws-sdk-go-v2/                                  
# github.com/aws/aws-sdk-go-v2
github.com/slsa-framework/slsa-verifier/v2/verifiers/internal/gha
github.com/sigstore/cosign/v2/cmd/cosign/cli/fulcio
github.com/sigstore/cosign/v2/cmd/cosign/cli/options
github.com/awslabs/amazon-ecr-credential-helper/ecr-login
github.com/awslabs/amazon-ecr-credential-helper/ecr-login/api
github.com/aws/aws-sdk-go-v2/config
github.com/aws/aws-sdk-go-v2/internal/ini
github.com/aws/aws-sdk-go-v2
```

Looking at our `gha` package we can see that the required methods from
fulcio are `Get()` and `GetIntermediates()`. Looking at the source
codes, we see that
`"github.com/sigstore/cosign/v2/cmd/cosign/cli/fulcio"`'s implementation
of these methods is the same as
`"github.com/sigstore/sigstore/pkg/fulcioroots"`'s implementation. So we
chose the latter's implementation, which happens to require fewer
module-level dependencies.

-
https://github.com/sigstore/cosign/blob/546f1c5b91ef58d6b034a402d0211d980184a0e5/cmd/cosign/cli/fulcio/fulcio.go#L16
-
https://github.com/sigstore/cosign/blob/546f1c5b91ef58d6b034a402d0211d980184a0e5/internal/pkg/cosign/fulcio/fulcioroots/fulcioroots.go#L16
-
https://github.com/sigstore/sigstore/blob/25dd9f3e52ec1e666b3c913edd1a0b7aa236b246/pkg/fulcioroots/fulcioroots.go#L17

## Testing

- unit tests continue to pass
- manual test to verify a provenance with the steps in our
[readme](https://github.com/slsa-framework/slsa-verifier?tab=readme-ov-file#npm-packages-built-using-the-slsa3-nodejs-builder)

## Future Work

The sigstore-go library is meant to be a more long-term solution, for
replacing much of the sigstore-related functionality that slsa-verifier
implements directly.

Signed-off-by: Ramon Petgrave <ramon.petgrave64@gmail.com>
2024-03-27 14:27:09 +00:00

77 lines
2.0 KiB
Go

package gha
import (
"context"
"crypto/x509"
"fmt"
"sync/atomic"
"github.com/sigstore/cosign/v2/pkg/cosign"
"github.com/sigstore/sigstore/pkg/fulcioroots"
serrors "github.com/slsa-framework/slsa-verifier/v2/errors"
)
// TrustedRoot struct that holds the verification material necessary
// to validate items. MUST be populated out of band.
type TrustedRoot struct {
// RekorPubKeys is a map from log ID to public keys containing metadata.
RekorPubKeys *cosign.TrustedTransparencyLogPubKeys
// SctPubKeys is a map from log ID to public keys for the SCT.
CTPubKeys *cosign.TrustedTransparencyLogPubKeys
// Certificate pool for Fulcio roots.
FulcioRoot *x509.CertPool
// Certificate pool for Fulcio intermediates
FulcioIntermediates *x509.CertPool
}
func getTrustedRoot(ctx context.Context) (*TrustedRoot, error) {
rekorPubKeys, err := cosign.GetRekorPubs(ctx)
if err != nil {
return nil, fmt.Errorf("%w: %s", serrors.ErrorRekorPubKey, err)
}
ctPubKeys, err := cosign.GetCTLogPubs(ctx)
if err != nil {
// this is unexpected, hold on to this error.
return nil, fmt.Errorf("%w: %s", serrors.ErrorInternal, err)
}
roots, err := fulcioroots.Get()
if err != nil {
// this is unexpected, hold on to this error.
return nil, fmt.Errorf("%w: %s", serrors.ErrorInternal, err)
}
intermediates, err := fulcioroots.GetIntermediates()
if err != nil {
// this is unexpected, hold on to this error.
return nil, fmt.Errorf("%w: %s", serrors.ErrorInternal, err)
}
return &TrustedRoot{
FulcioRoot: roots,
FulcioIntermediates: intermediates,
RekorPubKeys: rekorPubKeys,
CTPubKeys: ctPubKeys,
}, nil
}
// Cache the TUF roots to reduce traffic and read contention on the cached file.
var manager atomic.Value
func TrustedRootSingleton(ctx context.Context) (*TrustedRoot, error) {
root := manager.Load()
if root != nil {
return root.(*TrustedRoot), nil
}
trustedRoot, err := getTrustedRoot(ctx)
if err != nil {
return nil, err
}
manager.Store(trustedRoot)
return trustedRoot, nil
}