From dbc610b693f6b00bc296160eebe9d19a694376af Mon Sep 17 00:00:00 2001 From: Hayden Blauzvern Date: Fri, 20 May 2022 21:07:44 +0000 Subject: [PATCH] Add privacy statement for PII storage This statement has been added just before the OIDC code/normal flow, since only in this flow we expect a user to be present. For the device flow or when a token is provided, it's likely that Cosign is being run in an automated environment. This requires the user either type Y or provide a global flag for confirmation. This should not break any existing flows in automated environments because it's only the flow when a browser is needed, not for the device flow or when a token is provided. Signed-off-by: Hayden Blauzvern wip --- cmd/cosign/cli/commands.go | 6 ++++++ cmd/cosign/cli/fulcio/fulcio.go | 15 +++++++++++++++ cmd/cosign/cli/options/root.go | 10 +++++++--- pkg/cosign/common.go | 12 ++++++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/cmd/cosign/cli/commands.go b/cmd/cosign/cli/commands.go index 0d8765cc09c..ebbbe4169f3 100644 --- a/cmd/cosign/cli/commands.go +++ b/cmd/cosign/cli/commands.go @@ -26,6 +26,7 @@ import ( cranecmd "github.com/google/go-containerregistry/cmd/crane/cmd" "github.com/sigstore/cosign/cmd/cosign/cli/options" + "github.com/sigstore/cosign/pkg/cosign" ) var ( @@ -73,6 +74,11 @@ func New() *cobra.Command { if ro.Verbose { logs.Debug.SetOutput(os.Stderr) } + + if ro.Confirmation { + cosign.SetConfirmation(ro.Confirmation) + } + return nil }, PersistentPostRun: func(cmd *cobra.Command, args []string) { diff --git a/cmd/cosign/cli/fulcio/fulcio.go b/cmd/cosign/cli/fulcio/fulcio.go index b0ef7cf5d85..7939aaff043 100644 --- a/cmd/cosign/cli/fulcio/fulcio.go +++ b/cmd/cosign/cli/fulcio/fulcio.go @@ -22,6 +22,7 @@ import ( "crypto/rand" "crypto/sha256" "crypto/x509" + "errors" "fmt" "net/url" "os" @@ -41,6 +42,12 @@ const ( FlowNormal = "normal" FlowDevice = "device" FlowToken = "token" + // spacing is intentional to have this indented + PrivacyStatement = ` + Note that there may be personally identifiable information associated with this signed artifact. + This may include the email address associated with the account with which you authenticate. + This information will be used for signing this artifact and will be stored in public transparency logs and cannot be removed later. + By typing 'Y', you attest that you grant (or have permission to grant) and agree to have this information stored permanently in transparency logs.` ) type oidcConnector interface { @@ -92,6 +99,14 @@ func GetCert(ctx context.Context, priv *ecdsa.PrivateKey, idToken, flow, oidcIss c.flow = oauthflow.NewDeviceFlowTokenGetter( oidcIssuer, oauthflow.SigstoreDeviceURL, oauthflow.SigstoreTokenURL) case FlowNormal: + fmt.Fprintln(os.Stderr, PrivacyStatement) + ok, err := cosign.ConfirmPrompt("") + if err != nil { + return nil, err + } + if !ok { + return nil, errors.New("no confirmation") + } c.flow = oauthflow.DefaultIDTokenGetter case FlowToken: c.flow = &oauthflow.StaticTokenGetter{RawToken: idToken} diff --git a/cmd/cosign/cli/options/root.go b/cmd/cosign/cli/options/root.go index f42d92213b3..42c98335f94 100644 --- a/cmd/cosign/cli/options/root.go +++ b/cmd/cosign/cli/options/root.go @@ -23,9 +23,10 @@ import ( // RootOptions define flags and options for the root cosign cli. type RootOptions struct { - OutputFile string - Verbose bool - Timeout time.Duration + OutputFile string + Verbose bool + Timeout time.Duration + Confirmation bool } // DefaultTimeout specifies the default timeout for commands. @@ -43,4 +44,7 @@ func (o *RootOptions) AddFlags(cmd *cobra.Command) { cmd.PersistentFlags().DurationVarP(&o.Timeout, "timeout", "t", DefaultTimeout, "timeout for commands") + + cmd.PersistentFlags().BoolVarP(&o.Confirmation, "yes", "y", false, + "skip confirmation prompts") } diff --git a/pkg/cosign/common.go b/pkg/cosign/common.go index 4a8601c1cc7..0f29155d222 100644 --- a/pkg/cosign/common.go +++ b/pkg/cosign/common.go @@ -26,6 +26,14 @@ import ( "golang.org/x/term" ) +// confirmation is a global variable to store whether or not the user has provided +// the --yes flag to skip all confirmation prompts +var confirmation bool + +func SetConfirmation(confirm bool) { + confirmation = confirm +} + // TODO need to centralize this logic func FileExists(filename string) bool { info, err := os.Stat(filename) @@ -36,6 +44,10 @@ func FileExists(filename string) bool { } func ConfirmPrompt(msg string) (bool, error) { + if confirmation { + return confirmation, nil + } + fmt.Fprintf(os.Stderr, "%s\n\nAre you sure you want to continue? [Y/n]: ", msg) reader := bufio.NewReader(os.Stdin) r, err := reader.ReadString('\n')