Merge pull request #9000 from cli/andyfeller/flag-level-disableauth

proof of concept for flag-level disable auth check
This commit is contained in:
Andy Feller 2024-04-29 12:15:49 -04:00 committed by GitHub
commit 68dfd87f47
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 123 additions and 2 deletions

View file

@ -122,6 +122,7 @@ func NewVerifyCmd(f *cmdutil.Factory, runF func(*Options) error) *cobra.Command
// general flags
verifyCmd.Flags().StringVarP(&opts.BundlePath, "bundle", "b", "", "Path to bundle on disk, either a single bundle in a JSON file or a JSON lines file with multiple bundles")
cmdutil.DisableAuthCheckFlag(verifyCmd.Flags().Lookup("bundle"))
cmdutil.StringEnumFlag(verifyCmd, &opts.DigestAlgorithm, "digest-alg", "d", "sha256", []string{"sha256", "sha512"}, "The algorithm used to compute a digest of the artifact")
verifyCmd.Flags().StringVarP(&opts.Owner, "owner", "o", "", "GitHub organization to scope attestation lookup by")
verifyCmd.Flags().StringVarP(&opts.Repo, "repo", "R", "", "Repository name in the format <owner>/<repo>")

View file

@ -14,6 +14,7 @@ import (
"github.com/cli/cli/v2/pkg/cmd/attestation/test"
"github.com/cli/cli/v2/pkg/cmd/attestation/verification"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/spf13/cobra"
"github.com/cli/cli/v2/pkg/httpmock"
"github.com/cli/cli/v2/pkg/iostreams"
@ -237,6 +238,36 @@ func TestNewVerifyCmd(t *testing.T) {
}
}
func TestVerifyCmdAuthChecks(t *testing.T) {
f := &cmdutil.Factory{}
t.Run("by default auth check is required", func(t *testing.T) {
cmd := NewVerifyCmd(f, func(o *Options) error {
return nil
})
// IsAuthCheckEnabled assumes commands under test are subcommands
parent := &cobra.Command{Use: "root"}
parent.AddCommand(cmd)
require.NoError(t, cmd.ParseFlags([]string{}))
require.True(t, cmdutil.IsAuthCheckEnabled(cmd), "expected auth check to be required")
})
t.Run("when --bundle flag is provided, auth check is not required", func(t *testing.T) {
cmd := NewVerifyCmd(f, func(o *Options) error {
return nil
})
// IsAuthCheckEnabled assumes commands under test are subcommands
parent := &cobra.Command{Use: "root"}
parent.AddCommand(cmd)
require.NoError(t, cmd.ParseFlags([]string{"--bundle", "not-important"}))
require.False(t, cmdutil.IsAuthCheckEnabled(cmd), "expected auth check not to be required due to --bundle flag")
})
}
func TestJSONOutput(t *testing.T) {
testIO, _, out, _ := iostreams.Test()
opts := Options{

View file

@ -1,16 +1,29 @@
package cmdutil
import (
"reflect"
"github.com/cli/cli/v2/internal/config"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
const skipAuthCheckAnnotation = "skipAuthCheck"
func DisableAuthCheck(cmd *cobra.Command) {
if cmd.Annotations == nil {
cmd.Annotations = map[string]string{}
}
cmd.Annotations["skipAuthCheck"] = "true"
cmd.Annotations[skipAuthCheckAnnotation] = "true"
}
func DisableAuthCheckFlag(flag *pflag.Flag) {
if flag.Annotations == nil {
flag.Annotations = map[string][]string{}
}
flag.Annotations[skipAuthCheckAnnotation] = []string{"true"}
}
func CheckAuth(cfg config.Config) bool {
@ -32,7 +45,19 @@ func IsAuthCheckEnabled(cmd *cobra.Command) bool {
}
for c := cmd; c.Parent() != nil; c = c.Parent() {
if c.Annotations != nil && c.Annotations["skipAuthCheck"] == "true" {
// Check whether any command marked as DisableAuthCheck is set
if c.Annotations != nil && c.Annotations[skipAuthCheckAnnotation] == "true" {
return false
}
// Check whether any flag marked as DisableAuthCheckFlag is set
var skipAuthCheck bool
c.Flags().Visit(func(f *pflag.Flag) {
if f.Annotations != nil && reflect.DeepEqual(f.Annotations[skipAuthCheckAnnotation], []string{"true"}) {
skipAuthCheck = true
}
})
if skipAuthCheck {
return false
}
}

View file

@ -4,6 +4,7 @@ import (
"testing"
"github.com/cli/cli/v2/internal/config"
"github.com/spf13/cobra"
"github.com/stretchr/testify/require"
)
@ -53,3 +54,66 @@ func Test_CheckAuth(t *testing.T) {
})
}
}
func Test_IsAuthCheckEnabled(t *testing.T) {
tests := []struct {
name string
init func() (*cobra.Command, error)
isAuthCheckEnabled bool
}{
{
name: "no annotations",
init: func() (*cobra.Command, error) {
cmd := &cobra.Command{}
cmd.Flags().Bool("flag", false, "")
return cmd, nil
},
isAuthCheckEnabled: true,
},
{
name: "command-level disable",
init: func() (*cobra.Command, error) {
cmd := &cobra.Command{}
DisableAuthCheck(cmd)
return cmd, nil
},
isAuthCheckEnabled: false,
},
{
name: "command with flag-level disable, flag not set",
init: func() (*cobra.Command, error) {
cmd := &cobra.Command{}
cmd.Flags().Bool("flag", false, "")
DisableAuthCheckFlag(cmd.Flag("flag"))
return cmd, nil
},
isAuthCheckEnabled: true,
},
{
name: "command with flag-level disable, flag set",
init: func() (*cobra.Command, error) {
cmd := &cobra.Command{}
cmd.Flags().Bool("flag", false, "")
if err := cmd.Flags().Set("flag", "true"); err != nil {
return nil, err
}
DisableAuthCheckFlag(cmd.Flag("flag"))
return cmd, nil
},
isAuthCheckEnabled: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd, err := tt.init()
require.NoError(t, err)
// IsAuthCheckEnabled assumes commands under test are subcommands
parent := &cobra.Command{Use: "root"}
parent.AddCommand(cmd)
require.Equal(t, tt.isAuthCheckEnabled, IsAuthCheckEnabled(cmd))
})
}
}