Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: upgrade to OCI 1.1 #916

Merged
merged 21 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
shizhMSFT marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: ['1.20']
go-version: ['1.22']
fail-fast: true
steps:
- name: Set up Go ${{ matrix.go-version }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
security-events: write
strategy:
matrix:
go-version: ['1.20']
go-version: ['1.22']
fail-fast: false
steps:
- name: Checkout repository
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-github.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
go-version: ['1.20']
go-version: ['1.22']
fail-fast: true
steps:
- name: Set up Go ${{ matrix.go-version }}
Expand Down
2 changes: 1 addition & 1 deletion building.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The notation repo contains the following:

- `notation` - A CLI for signing and verifying artifacts with Notation

Building above binaries require [golang](https://golang.org/dl/) with version `>= 1.20`.
Building above binaries require [golang](https://golang.org/dl/) with version `>= 1.21`.
Two-Hearts marked this conversation as resolved.
Show resolved Hide resolved

## Windows with WSL or Linux

Expand Down
21 changes: 6 additions & 15 deletions cmd/notation/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"github.com/notaryproject/notation-go/plugin/proto"
"github.com/notaryproject/notation-go/registry"
cmderr "github.com/notaryproject/notation/cmd/notation/internal/errors"
"github.com/notaryproject/notation/cmd/notation/internal/experimental"
"github.com/notaryproject/notation/internal/cmd"
"github.com/notaryproject/notation/internal/envelope"
"github.com/notaryproject/notation/internal/ioutil"
Expand All @@ -40,10 +39,9 @@ import (
type inspectOpts struct {
cmd.LoggingFlagOpts
SecureFlagOpts
reference string
outputFormat string
allowReferrersAPI bool
maxSignatures int
reference string
outputFormat string
maxSignatures int
}

type inspectOutput struct {
Expand Down Expand Up @@ -83,10 +81,6 @@ Example - Inspect signatures on an OCI artifact identified by a tag (Notation w

Example - Inspect signatures on an OCI artifact identified by a digest and output as json:
notation inspect --output json <registry>/<repository>@<digest>
`
experimentalExamples := `
Example - [Experimental] Inspect signatures on an OCI artifact identified by a digest using the Referrers API, if not supported (returns 404), fallback to the Referrers tag schema
notation inspect --allow-referrers-api <registry>/<repository>@<digest>
`
command := &cobra.Command{
Use: "inspect [reference]",
Expand All @@ -99,9 +93,6 @@ Example - [Experimental] Inspect signatures on an OCI artifact identified by a d
opts.reference = args[0]
return nil
},
PreRunE: func(cmd *cobra.Command, args []string) error {
return experimental.CheckFlagsAndWarn(cmd, "allow-referrers-api")
},
RunE: func(cmd *cobra.Command, args []string) error {
if opts.maxSignatures <= 0 {
return fmt.Errorf("max-signatures value %d must be a positive number", opts.maxSignatures)
Expand All @@ -114,8 +105,6 @@ Example - [Experimental] Inspect signatures on an OCI artifact identified by a d
opts.SecureFlagOpts.ApplyFlags(command.Flags())
cmd.SetPflagOutput(command.Flags(), &opts.outputFormat, cmd.PflagOutputUsage)
command.Flags().IntVar(&opts.maxSignatures, "max-signatures", 100, "maximum number of signatures to evaluate or examine")
cmd.SetPflagReferrersAPI(command.Flags(), &opts.allowReferrersAPI, fmt.Sprintf(cmd.PflagReferrersUsageFormat, "inspect"))
experimental.HideFlags(command, experimentalExamples, []string{"allow-referrers-api"})
return command
}

Expand All @@ -129,7 +118,9 @@ func runInspect(command *cobra.Command, opts *inspectOpts) error {

// initialize
reference := opts.reference
sigRepo, err := getRemoteRepository(ctx, &opts.SecureFlagOpts, reference, opts.allowReferrersAPI)
// always use the Referrers API, if not supported, automatically fallback to
// the referrers tag schema
sigRepo, err := getRemoteRepository(ctx, &opts.SecureFlagOpts, reference, true)
if err != nil {
return err
}
Expand Down
22 changes: 9 additions & 13 deletions cmd/notation/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@ import (
type listOpts struct {
cmd.LoggingFlagOpts
SecureFlagOpts
reference string
allowReferrersAPI bool
ociLayout bool
inputType inputType
maxSignatures int
reference string
ociLayout bool
inputType inputType
maxSignatures int
}

func listCommand(opts *listOpts) *cobra.Command {
Expand All @@ -52,9 +51,6 @@ Example - List signatures of an OCI artifact identified by a tag (Notation will
notation list <registry>/<repository>:<tag>
`
experimentalExamples := `
Example - [Experimental] List signatures of an OCI artifact using the Referrers API. If it's not supported (returns 404), fallback to the Referrers tag schema
notation list --allow-referrers-api <registry>/<repository>@<digest>

Example - [Experimental] List signatures of an OCI artifact referenced in an OCI layout
notation list --oci-layout "<oci_layout_path>@<digest>"

Expand All @@ -77,7 +73,7 @@ Example - [Experimental] List signatures of an OCI artifact identified by a tag
if opts.ociLayout {
opts.inputType = inputTypeOCILayout
}
return experimental.CheckFlagsAndWarn(cmd, "allow-referrers-api", "oci-layout")
return experimental.CheckFlagsAndWarn(cmd, "oci-layout")
},
RunE: func(cmd *cobra.Command, args []string) error {
if opts.maxSignatures <= 0 {
Expand All @@ -88,11 +84,9 @@ Example - [Experimental] List signatures of an OCI artifact identified by a tag
}
opts.LoggingFlagOpts.ApplyFlags(command.Flags())
opts.SecureFlagOpts.ApplyFlags(command.Flags())
cmd.SetPflagReferrersAPI(command.Flags(), &opts.allowReferrersAPI, fmt.Sprintf(cmd.PflagReferrersUsageFormat, "list"))
command.Flags().BoolVar(&opts.ociLayout, "oci-layout", false, "[Experimental] list signatures stored in OCI image layout")
experimental.HideFlags(command, "", []string{"allow-referrers-api", "oci-layout"})
Two-Hearts marked this conversation as resolved.
Show resolved Hide resolved
command.Flags().IntVar(&opts.maxSignatures, "max-signatures", 100, "maximum number of signatures to evaluate or examine")
experimental.HideFlags(command, experimentalExamples, []string{"allow-referrers-api", "oci-layout"})
experimental.HideFlags(command, experimentalExamples, []string{"oci-layout"})
return command
}

Expand All @@ -102,7 +96,9 @@ func runList(ctx context.Context, opts *listOpts) error {

// initialize
reference := opts.reference
sigRepo, err := getRepository(ctx, opts.inputType, reference, &opts.SecureFlagOpts, opts.allowReferrersAPI)
// always use the Referrers API, if not supported, automatically fallback to
// the referrers tag schema
sigRepo, err := getRepository(ctx, opts.inputType, reference, &opts.SecureFlagOpts, true)
if err != nil {
return err
}
Expand Down
25 changes: 12 additions & 13 deletions cmd/notation/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (

"github.com/notaryproject/notation-go/log"
notationregistry "github.com/notaryproject/notation-go/registry"
"github.com/notaryproject/notation/cmd/notation/internal/experimental"
notationauth "github.com/notaryproject/notation/internal/auth"
"github.com/notaryproject/notation/internal/httputil"
"github.com/notaryproject/notation/pkg/configutil"
Expand All @@ -41,10 +40,10 @@ const (

// getRepository returns a notationregistry.Repository given user input
// type and user input reference
func getRepository(ctx context.Context, inputType inputType, reference string, opts *SecureFlagOpts, allowReferrersAPI bool) (notationregistry.Repository, error) {
func getRepository(ctx context.Context, inputType inputType, reference string, opts *SecureFlagOpts, useReferrersAPI bool) (notationregistry.Repository, error) {
switch inputType {
case inputTypeRegistry:
return getRemoteRepository(ctx, opts, reference, allowReferrersAPI)
return getRemoteRepository(ctx, opts, reference, useReferrersAPI)
case inputTypeOCILayout:
layoutPath, _, err := parseOCILayoutReference(reference)
if err != nil {
Expand All @@ -57,17 +56,17 @@ func getRepository(ctx context.Context, inputType inputType, reference string, o
}

// getRemoteRepository returns a registry.Repository.
// When experimental feature is disabled OR allowReferrersAPI is not set,
// Notation always uses referrers tag schema to store and consume signatures
// by default.
// When experimental feature is enabled AND allowReferrersAPI is set, Notation
// tries the Referrers API, if not supported, fallback to use the Referrers
// tag schema.
// When useReferrersAPI is set, Notation tries the Referrers API,
// if not supported, fallback to use the Referrers tag schema. This flag is
// always set when verify/list/inspect signatures.
//
// When useReferrersAPI is not set, Notation uses referrers tag schema
// to store signatures by default.
//
// References:
// https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#listing-referrers
// https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#referrers-tag-schema
func getRemoteRepository(ctx context.Context, opts *SecureFlagOpts, reference string, allowReferrersAPI bool) (notationregistry.Repository, error) {
// https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#listing-referrers
// https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#referrers-tag-schema
func getRemoteRepository(ctx context.Context, opts *SecureFlagOpts, reference string, useReferrersAPI bool) (notationregistry.Repository, error) {
logger := log.GetLogger(ctx)
ref, err := registry.ParseReference(reference)
if err != nil {
Expand All @@ -82,7 +81,7 @@ func getRemoteRepository(ctx context.Context, opts *SecureFlagOpts, reference st
return nil, err
}

if !experimental.IsDisabled() && allowReferrersAPI {
if useReferrersAPI {
logger.Info("Trying to use the referrers API")
} else {
logger.Info("Using the referrers tag schema")
Expand Down
10 changes: 0 additions & 10 deletions cmd/notation/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,13 @@ import (
"net/http/httptest"
"net/url"
"testing"

"github.com/notaryproject/notation/cmd/notation/internal/experimental"
)

const (
zeroDigest = "sha256:0000000000000000000000000000000000000000000000000000000000000000"
)

func TestRegistry_getRemoteRepositoryWithReferrersAPISupported(t *testing.T) {
t.Setenv("NOTATION_EXPERIMENTAL", "1")
if experimental.IsDisabled() {
t.Fatal("failed to enable experimental")
}
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodGet && r.URL.Path == "/v2/test/v1/referrers/"+zeroDigest {
w.WriteHeader(http.StatusOK)
Expand All @@ -56,10 +50,6 @@ func TestRegistry_getRemoteRepositoryWithReferrersAPISupported(t *testing.T) {
}

func TestRegistry_getRemoteRepositoryWithReferrersAPINotSupported(t *testing.T) {
t.Setenv("NOTATION_EXPERIMENTAL", "1")
if experimental.IsDisabled() {
t.Fatal("failed to enable experimental")
}
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodGet && r.URL.Path == "/v2/test/v1/referrers/"+zeroDigest {
w.WriteHeader(http.StatusNotFound)
Expand Down
15 changes: 6 additions & 9 deletions cmd/notation/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ Example - Sign an OCI artifact identified by a tag (Notation will resolve tag to

Example - Sign an OCI artifact stored in a registry and specify the signature expiry duration, for example 24 hours
notation sign --expiry 24h <registry>/<repository>@<digest>

Example - Sign an OCI artifact and store signature using the Referrers API. If it's not supported (returns 404), fallback to the Referrers tag schema
notation sign --allow-referrers-api <registry>/<repository>@<digest>
`
experimentalExamples := `
Example - [Experimental] Sign an OCI artifact and store signature using the Referrers API. If it's not supported (returns 404), fallback to the Referrers tag schema
notation sign --allow-referrers-api <registry>/<repository>@<digest>

Example - [Experimental] Sign an OCI artifact referenced in an OCI layout
notation sign --oci-layout "<oci_layout_path>@<digest>"

Expand All @@ -99,7 +99,7 @@ Example - [Experimental] Sign an OCI artifact identified by a tag and referenced
if opts.ociLayout {
opts.inputType = inputTypeOCILayout
}
return experimental.CheckFlagsAndWarn(cmd, "allow-referrers-api", "oci-layout")
return experimental.CheckFlagsAndWarn(cmd, "oci-layout")
},
RunE: func(cmd *cobra.Command, args []string) error {
return runSign(cmd, opts)
Expand All @@ -111,10 +111,10 @@ Example - [Experimental] Sign an OCI artifact identified by a tag and referenced
cmd.SetPflagExpiry(command.Flags(), &opts.expiry)
cmd.SetPflagPluginConfig(command.Flags(), &opts.pluginConfig)
cmd.SetPflagUserMetadata(command.Flags(), &opts.userMetadata, cmd.PflagUserMetadataSignUsage)
cmd.SetPflagReferrersAPI(command.Flags(), &opts.allowReferrersAPI, fmt.Sprintf(cmd.PflagReferrersUsageFormat, "sign"))
cmd.SetPflagReferrersAPI(command.Flags(), &opts.allowReferrersAPI, "use the Referrers API to store signatures, if not supported (returns 404), fallback to the Referrers tag schema")
command.Flags().BoolVar(&opts.ociLayout, "oci-layout", false, "[Experimental] sign the artifact stored as OCI image layout")
command.MarkFlagsMutuallyExclusive("oci-layout", "allow-referrers-api")
experimental.HideFlags(command, experimentalExamples, []string{"allow-referrers-api", "oci-layout"})
experimental.HideFlags(command, experimentalExamples, []string{"oci-layout"})
return command
}

Expand All @@ -127,9 +127,6 @@ func runSign(command *cobra.Command, cmdOpts *signOpts) error {
if err != nil {
return err
}
if cmdOpts.allowReferrersAPI {
fmt.Fprintln(os.Stderr, "Warning: using the Referrers API to store signature. On success, must set the `--allow-referrers-api` flag to list, inspect, and verify the signature.")
}
sigRepo, err := getRepository(ctx, cmdOpts.inputType, cmdOpts.reference, &cmdOpts.SecureFlagOpts, cmdOpts.allowReferrersAPI)
if err != nil {
return err
Expand Down
13 changes: 5 additions & 8 deletions cmd/notation/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ type verifyOpts struct {
reference string
pluginConfig []string
userMetadata []string
allowReferrersAPI bool
ociLayout bool
trustPolicyScope string
inputType inputType
Expand All @@ -60,9 +59,6 @@ Example - Verify a signature on an OCI artifact identified by a tag (Notation w
notation verify <registry>/<repository>:<tag>
`
experimentalExamples := `
Example - [Experimental] Verify an OCI artifact using the Referrers API, if not supported (returns 404), fallback to the Referrers tag schema
notation verify --allow-referrers-api <registry>/<repository>@<digest>

Example - [Experimental] Verify a signature on an OCI artifact referenced in an OCI layout using trust policy statement specified by scope.
notation verify --oci-layout <registry>/<repository>@<digest> --scope <trust_policy_scope>

Expand All @@ -84,7 +80,7 @@ Example - [Experimental] Verify a signature on an OCI artifact identified by a t
if opts.ociLayout {
opts.inputType = inputTypeOCILayout
}
return experimental.CheckFlagsAndWarn(cmd, "allow-referrers-api", "oci-layout", "scope")
return experimental.CheckFlagsAndWarn(cmd, "oci-layout", "scope")
},
RunE: func(cmd *cobra.Command, args []string) error {
if opts.maxSignatureAttempts <= 0 {
Expand All @@ -98,11 +94,10 @@ Example - [Experimental] Verify a signature on an OCI artifact identified by a t
command.Flags().StringArrayVar(&opts.pluginConfig, "plugin-config", nil, "{key}={value} pairs that are passed as it is to a plugin, if the verification is associated with a verification plugin, refer plugin documentation to set appropriate values")
cmd.SetPflagUserMetadata(command.Flags(), &opts.userMetadata, cmd.PflagUserMetadataVerifyUsage)
command.Flags().IntVar(&opts.maxSignatureAttempts, "max-signatures", 100, "maximum number of signatures to evaluate or examine")
cmd.SetPflagReferrersAPI(command.Flags(), &opts.allowReferrersAPI, fmt.Sprintf(cmd.PflagReferrersUsageFormat, "verify"))
command.Flags().BoolVar(&opts.ociLayout, "oci-layout", false, "[Experimental] verify the artifact stored as OCI image layout")
command.Flags().StringVar(&opts.trustPolicyScope, "scope", "", "[Experimental] set trust policy scope for artifact verification, required and can only be used when flag \"--oci-layout\" is set")
command.MarkFlagsRequiredTogether("oci-layout", "scope")
experimental.HideFlags(command, experimentalExamples, []string{"allow-referrers-api", "oci-layout", "scope"})
experimental.HideFlags(command, experimentalExamples, []string{"oci-layout", "scope"})
return command
}

Expand Down Expand Up @@ -130,7 +125,9 @@ func runVerify(command *cobra.Command, opts *verifyOpts) error {

// core verify process
reference := opts.reference
sigRepo, err := getRepository(ctx, opts.inputType, reference, &opts.SecureFlagOpts, opts.allowReferrersAPI)
// always use the Referrers API, if not supported, automatically fallback to
// the referrers tag schema
sigRepo, err := getRepository(ctx, opts.inputType, reference, &opts.SecureFlagOpts, true)
if err != nil {
return err
}
Expand Down
15 changes: 8 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
module github.com/notaryproject/notation

go 1.21
go 1.22

require (
github.com/notaryproject/notation-core-go v1.0.2
github.com/notaryproject/notation-go v1.1.1-0.20240201073933-4606472ebdcb
github.com/notaryproject/notation-core-go v1.0.3-0.20240325061945-807a3386734e
github.com/notaryproject/notation-go v1.1.1-0.20240327165254-57ff8e68a0a8
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5
golang.org/x/term v0.18.0
oras.land/oras-go/v2 v2.4.0
oras.land/oras-go/v2 v2.5.0
)

require (
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/fxamacker/cbor/v2 v2.5.0 // indirect
github.com/fxamacker/cbor/v2 v2.6.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
github.com/go-ldap/ldap/v3 v3.4.6 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/notaryproject/notation-plugin-framework-go v1.0.0 // indirect
github.com/veraison/go-cose v1.1.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/mod v0.16.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.18.0 // indirect
)
Loading
Loading