mirror of
https://github.com/containers/podman.git
synced 2026-03-27 11:03:09 -04:00
Consolidate the definition and consumption of --sign* CLI options
There are three copies of them, and already a shared utility, so also define the options in a single place. This will make it easier to add more options, and it reduces the risk of incorrectly ordering the parameters to PrepareSigning. Should not change behavior. Signed-off-by: Miloslav Trmač <mitr@redhat.com>
This commit is contained in:
@@ -19,13 +19,12 @@ import (
|
||||
// CLI-only fields into the API types.
|
||||
type pushOptionsWrapper struct {
|
||||
entities.ArtifactPushOptions
|
||||
TLSVerifyCLI bool // CLI only
|
||||
CredentialsCLI string
|
||||
SignPassphraseFileCLI string
|
||||
SignBySigstoreParamFileCLI string
|
||||
EncryptionKeys []string
|
||||
EncryptLayers []int
|
||||
DigestFile string
|
||||
TLSVerifyCLI bool // CLI only
|
||||
CredentialsCLI string
|
||||
signing common.SigningCLIOnlyOptions
|
||||
EncryptionKeys []string
|
||||
EncryptLayers []int
|
||||
DigestFile string
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -87,21 +86,7 @@ func pushFlags(cmd *cobra.Command) {
|
||||
flags.String(retryDelayFlagName, registry.RetryDelayDefault(), "delay between retries in case of push failures")
|
||||
_ = cmd.RegisterFlagCompletionFunc(retryDelayFlagName, completion.AutocompleteNone)
|
||||
|
||||
signByFlagName := "sign-by"
|
||||
flags.StringVar(&pushOptions.SignBy, signByFlagName, "", "Add a signature at the destination using the specified key")
|
||||
_ = cmd.RegisterFlagCompletionFunc(signByFlagName, completion.AutocompleteNone)
|
||||
|
||||
signBySigstoreFlagName := "sign-by-sigstore"
|
||||
flags.StringVar(&pushOptions.SignBySigstoreParamFileCLI, signBySigstoreFlagName, "", "Sign the image using a sigstore parameter file at `PATH`")
|
||||
_ = cmd.RegisterFlagCompletionFunc(signBySigstoreFlagName, completion.AutocompleteDefault)
|
||||
|
||||
signBySigstorePrivateKeyFlagName := "sign-by-sigstore-private-key"
|
||||
flags.StringVar(&pushOptions.SignBySigstorePrivateKeyFile, signBySigstorePrivateKeyFlagName, "", "Sign the image using a sigstore private key at `PATH`")
|
||||
_ = cmd.RegisterFlagCompletionFunc(signBySigstorePrivateKeyFlagName, completion.AutocompleteDefault)
|
||||
|
||||
signPassphraseFileFlagName := "sign-passphrase-file"
|
||||
flags.StringVar(&pushOptions.SignPassphraseFileCLI, signPassphraseFileFlagName, "", "Read a passphrase for signing an image from `PATH`")
|
||||
_ = cmd.RegisterFlagCompletionFunc(signPassphraseFileFlagName, completion.AutocompleteDefault)
|
||||
common.DefineSigningFlags(cmd, &pushOptions.signing, &pushOptions.ArtifactPushOptions.ImagePushOptions)
|
||||
|
||||
flags.BoolVar(&pushOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
|
||||
|
||||
@@ -130,10 +115,6 @@ func pushFlags(cmd *cobra.Command) {
|
||||
_ = flags.MarkHidden("cert-dir")
|
||||
_ = flags.MarkHidden("compress")
|
||||
_ = flags.MarkHidden("quiet")
|
||||
_ = flags.MarkHidden(signByFlagName)
|
||||
_ = flags.MarkHidden(signBySigstoreFlagName)
|
||||
_ = flags.MarkHidden(signBySigstorePrivateKeyFlagName)
|
||||
_ = flags.MarkHidden(signPassphraseFileFlagName)
|
||||
} else {
|
||||
signaturePolicyFlagName := "signature-policy"
|
||||
flags.StringVar(&pushOptions.SignaturePolicy, signaturePolicyFlagName, "", "Path to a signature-policy file")
|
||||
@@ -173,8 +154,7 @@ func artifactPush(cmd *cobra.Command, args []string) error {
|
||||
pushOptions.Writer = os.Stderr
|
||||
}
|
||||
|
||||
signingCleanup, err := common.PrepareSigning(&pushOptions.ImagePushOptions,
|
||||
pushOptions.SignPassphraseFileCLI, pushOptions.SignBySigstoreParamFileCLI)
|
||||
signingCleanup, err := common.PrepareSigning(&pushOptions.ImagePushOptions, &pushOptions.signing)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,30 +4,66 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/containers/common/pkg/completion"
|
||||
"github.com/containers/common/pkg/ssh"
|
||||
"github.com/containers/image/v5/pkg/cli"
|
||||
"github.com/containers/image/v5/pkg/cli/sigstore"
|
||||
"github.com/containers/image/v5/signature/signer"
|
||||
"github.com/containers/podman/v5/cmd/podman/registry"
|
||||
"github.com/containers/podman/v5/pkg/domain/entities"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// PrepareSigning updates pushOpts.Signers, pushOpts.SignPassphrase and SignSigstorePrivateKeyPassphrase based on a --sign-passphrase-file
|
||||
// value signPassphraseFile and a --sign-by-sigsstore value signBySigstoreParamFile, and validates pushOpts.Sign* consistency.
|
||||
// SigningCLIOnlyOptions contains signing-related CLI options.
|
||||
// Some other options are defined in entities.ImagePushOptions.
|
||||
type SigningCLIOnlyOptions struct {
|
||||
signPassphraseFile string
|
||||
signBySigstoreParamFile string
|
||||
}
|
||||
|
||||
func DefineSigningFlags(cmd *cobra.Command, cliOpts *SigningCLIOnlyOptions, pushOpts *entities.ImagePushOptions) {
|
||||
flags := cmd.Flags()
|
||||
|
||||
signByFlagName := "sign-by"
|
||||
flags.StringVar(&pushOpts.SignBy, signByFlagName, "", "Add a signature at the destination using the specified key")
|
||||
_ = cmd.RegisterFlagCompletionFunc(signByFlagName, completion.AutocompleteNone)
|
||||
|
||||
signBySigstoreFlagName := "sign-by-sigstore"
|
||||
flags.StringVar(&cliOpts.signBySigstoreParamFile, signBySigstoreFlagName, "", "Sign the image using a sigstore parameter file at `PATH`")
|
||||
_ = cmd.RegisterFlagCompletionFunc(signBySigstoreFlagName, completion.AutocompleteDefault)
|
||||
|
||||
signBySigstorePrivateKeyFlagName := "sign-by-sigstore-private-key"
|
||||
flags.StringVar(&pushOpts.SignBySigstorePrivateKeyFile, signBySigstorePrivateKeyFlagName, "", "Sign the image using a sigstore private key at `PATH`")
|
||||
_ = cmd.RegisterFlagCompletionFunc(signBySigstorePrivateKeyFlagName, completion.AutocompleteDefault)
|
||||
|
||||
signPassphraseFileFlagName := "sign-passphrase-file"
|
||||
flags.StringVar(&cliOpts.signPassphraseFile, signPassphraseFileFlagName, "", "Read a passphrase for signing an image from `PATH`")
|
||||
_ = cmd.RegisterFlagCompletionFunc(signPassphraseFileFlagName, completion.AutocompleteDefault)
|
||||
|
||||
if registry.IsRemote() {
|
||||
_ = flags.MarkHidden(signByFlagName)
|
||||
_ = flags.MarkHidden(signBySigstoreFlagName)
|
||||
_ = flags.MarkHidden(signBySigstorePrivateKeyFlagName)
|
||||
_ = flags.MarkHidden(signPassphraseFileFlagName)
|
||||
}
|
||||
}
|
||||
|
||||
// PrepareSigning updates pushOpts.Signers, pushOpts.SignPassphrase and SignSigstorePrivateKeyPassphrase based on cliOpts,
|
||||
// and validates pushOpts.Sign* consistency.
|
||||
// It may interactively prompt for a passphrase if one is required and wasn’t provided otherwise;
|
||||
// or it may interactively trigger an OIDC authentication, using standard input/output, or even open a web browser.
|
||||
// Returns a cleanup callback on success, which must be called when done.
|
||||
func PrepareSigning(pushOpts *entities.ImagePushOptions,
|
||||
signPassphraseFile, signBySigstoreParamFile string) (func(), error) {
|
||||
func PrepareSigning(pushOpts *entities.ImagePushOptions, cliOpts *SigningCLIOnlyOptions) (func(), error) {
|
||||
// c/common/libimage.Image does allow creating both simple signing and sigstore signatures simultaneously,
|
||||
// with independent passphrases, but that would make the CLI probably too confusing.
|
||||
// For now, use the passphrase with either, but only one of them.
|
||||
if signPassphraseFile != "" && pushOpts.SignBy != "" && pushOpts.SignBySigstorePrivateKeyFile != "" {
|
||||
if cliOpts.signPassphraseFile != "" && pushOpts.SignBy != "" && pushOpts.SignBySigstorePrivateKeyFile != "" {
|
||||
return nil, fmt.Errorf("only one of --sign-by and sign-by-sigstore-private-key can be used with --sign-passphrase-file")
|
||||
}
|
||||
|
||||
var passphrase string
|
||||
if signPassphraseFile != "" {
|
||||
p, err := cli.ReadPassphraseFile(signPassphraseFile)
|
||||
if cliOpts.signPassphraseFile != "" {
|
||||
p, err := cli.ReadPassphraseFile(cliOpts.signPassphraseFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -39,8 +75,8 @@ func PrepareSigning(pushOpts *entities.ImagePushOptions,
|
||||
pushOpts.SignPassphrase = passphrase
|
||||
pushOpts.SignSigstorePrivateKeyPassphrase = []byte(passphrase)
|
||||
cleanup := signingCleanup{}
|
||||
if signBySigstoreParamFile != "" {
|
||||
signer, err := sigstore.NewSignerFromParameterFile(signBySigstoreParamFile, &sigstore.Options{
|
||||
if cliOpts.signBySigstoreParamFile != "" {
|
||||
signer, err := sigstore.NewSignerFromParameterFile(cliOpts.signBySigstoreParamFile, &sigstore.Options{
|
||||
PrivateKeyPassphrasePrompt: cli.ReadPassphraseFile,
|
||||
Stdin: os.Stdin,
|
||||
Stdout: os.Stdout,
|
||||
|
||||
@@ -19,13 +19,12 @@ import (
|
||||
// CLI-only fields into the API types.
|
||||
type pushOptionsWrapper struct {
|
||||
entities.ImagePushOptions
|
||||
TLSVerifyCLI bool // CLI only
|
||||
CredentialsCLI string
|
||||
SignPassphraseFileCLI string
|
||||
SignBySigstoreParamFileCLI string
|
||||
EncryptionKeys []string
|
||||
EncryptLayers []int
|
||||
DigestFile string
|
||||
TLSVerifyCLI bool // CLI only
|
||||
CredentialsCLI string
|
||||
signing common.SigningCLIOnlyOptions
|
||||
EncryptionKeys []string
|
||||
EncryptLayers []int
|
||||
DigestFile string
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -118,21 +117,7 @@ func pushFlags(cmd *cobra.Command) {
|
||||
flags.String(retryDelayFlagName, registry.RetryDelayDefault(), "delay between retries in case of push failures")
|
||||
_ = cmd.RegisterFlagCompletionFunc(retryDelayFlagName, completion.AutocompleteNone)
|
||||
|
||||
signByFlagName := "sign-by"
|
||||
flags.StringVar(&pushOptions.SignBy, signByFlagName, "", "Add a signature at the destination using the specified key")
|
||||
_ = cmd.RegisterFlagCompletionFunc(signByFlagName, completion.AutocompleteNone)
|
||||
|
||||
signBySigstoreFlagName := "sign-by-sigstore"
|
||||
flags.StringVar(&pushOptions.SignBySigstoreParamFileCLI, signBySigstoreFlagName, "", "Sign the image using a sigstore parameter file at `PATH`")
|
||||
_ = cmd.RegisterFlagCompletionFunc(signBySigstoreFlagName, completion.AutocompleteDefault)
|
||||
|
||||
signBySigstorePrivateKeyFlagName := "sign-by-sigstore-private-key"
|
||||
flags.StringVar(&pushOptions.SignBySigstorePrivateKeyFile, signBySigstorePrivateKeyFlagName, "", "Sign the image using a sigstore private key at `PATH`")
|
||||
_ = cmd.RegisterFlagCompletionFunc(signBySigstorePrivateKeyFlagName, completion.AutocompleteDefault)
|
||||
|
||||
signPassphraseFileFlagName := "sign-passphrase-file"
|
||||
flags.StringVar(&pushOptions.SignPassphraseFileCLI, signPassphraseFileFlagName, "", "Read a passphrase for signing an image from `PATH`")
|
||||
_ = cmd.RegisterFlagCompletionFunc(signPassphraseFileFlagName, completion.AutocompleteDefault)
|
||||
common.DefineSigningFlags(cmd, &pushOptions.signing, &pushOptions.ImagePushOptions)
|
||||
|
||||
flags.BoolVar(&pushOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
|
||||
|
||||
@@ -156,10 +141,6 @@ func pushFlags(cmd *cobra.Command) {
|
||||
_ = flags.MarkHidden("cert-dir")
|
||||
_ = flags.MarkHidden("compress")
|
||||
_ = flags.MarkHidden("quiet")
|
||||
_ = flags.MarkHidden(signByFlagName)
|
||||
_ = flags.MarkHidden(signBySigstoreFlagName)
|
||||
_ = flags.MarkHidden(signBySigstorePrivateKeyFlagName)
|
||||
_ = flags.MarkHidden(signPassphraseFileFlagName)
|
||||
_ = flags.MarkHidden(encryptionKeysFlagName)
|
||||
_ = flags.MarkHidden(encryptLayersFlagName)
|
||||
} else {
|
||||
@@ -201,8 +182,7 @@ func imagePush(cmd *cobra.Command, args []string) error {
|
||||
pushOptions.Writer = os.Stderr
|
||||
}
|
||||
|
||||
signingCleanup, err := common.PrepareSigning(&pushOptions.ImagePushOptions,
|
||||
pushOptions.SignPassphraseFileCLI, pushOptions.SignBySigstoreParamFileCLI)
|
||||
signingCleanup, err := common.PrepareSigning(&pushOptions.ImagePushOptions, &pushOptions.signing)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -21,11 +21,10 @@ import (
|
||||
type manifestPushOptsWrapper struct {
|
||||
entities.ImagePushOptions
|
||||
|
||||
TLSVerifyCLI, Insecure bool // CLI only
|
||||
CredentialsCLI string
|
||||
SignBySigstoreParamFileCLI string
|
||||
SignPassphraseFileCLI string
|
||||
DigestFile string
|
||||
TLSVerifyCLI, Insecure bool // CLI only
|
||||
CredentialsCLI string
|
||||
signing common.SigningCLIOnlyOptions
|
||||
DigestFile string
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -81,21 +80,7 @@ func init() {
|
||||
|
||||
flags.BoolVarP(&manifestPushOpts.RemoveSignatures, "remove-signatures", "", false, "don't copy signatures when pushing images")
|
||||
|
||||
signByFlagName := "sign-by"
|
||||
flags.StringVar(&manifestPushOpts.SignBy, signByFlagName, "", "sign the image using a GPG key with the specified `FINGERPRINT`")
|
||||
_ = pushCmd.RegisterFlagCompletionFunc(signByFlagName, completion.AutocompleteNone)
|
||||
|
||||
signBySigstoreFlagName := "sign-by-sigstore"
|
||||
flags.StringVar(&manifestPushOpts.SignBySigstoreParamFileCLI, signBySigstoreFlagName, "", "Sign the image using a sigstore parameter file at `PATH`")
|
||||
_ = pushCmd.RegisterFlagCompletionFunc(signBySigstoreFlagName, completion.AutocompleteDefault)
|
||||
|
||||
signBySigstorePrivateKeyFlagName := "sign-by-sigstore-private-key"
|
||||
flags.StringVar(&manifestPushOpts.SignBySigstorePrivateKeyFile, signBySigstorePrivateKeyFlagName, "", "Sign the image using a sigstore private key at `PATH`")
|
||||
_ = pushCmd.RegisterFlagCompletionFunc(signBySigstorePrivateKeyFlagName, completion.AutocompleteDefault)
|
||||
|
||||
signPassphraseFileFlagName := "sign-passphrase-file"
|
||||
flags.StringVar(&manifestPushOpts.SignPassphraseFileCLI, signPassphraseFileFlagName, "", "Read a passphrase for signing an image from `PATH`")
|
||||
_ = pushCmd.RegisterFlagCompletionFunc(signPassphraseFileFlagName, completion.AutocompleteDefault)
|
||||
common.DefineSigningFlags(pushCmd, &manifestPushOpts.signing, &manifestPushOpts.ImagePushOptions)
|
||||
|
||||
flags.BoolVar(&manifestPushOpts.TLSVerifyCLI, "tls-verify", true, "require HTTPS and verify certificates when accessing the registry")
|
||||
flags.BoolVar(&manifestPushOpts.Insecure, "insecure", false, "neither require HTTPS nor verify certificates when accessing the registry")
|
||||
@@ -113,10 +98,6 @@ func init() {
|
||||
|
||||
if registry.IsRemote() {
|
||||
_ = flags.MarkHidden("cert-dir")
|
||||
_ = flags.MarkHidden(signByFlagName)
|
||||
_ = flags.MarkHidden(signBySigstoreFlagName)
|
||||
_ = flags.MarkHidden(signBySigstorePrivateKeyFlagName)
|
||||
_ = flags.MarkHidden(signPassphraseFileFlagName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,8 +129,7 @@ func push(cmd *cobra.Command, args []string) error {
|
||||
manifestPushOpts.Writer = os.Stderr
|
||||
}
|
||||
|
||||
signingCleanup, err := common.PrepareSigning(&manifestPushOpts.ImagePushOptions,
|
||||
manifestPushOpts.SignPassphraseFileCLI, manifestPushOpts.SignBySigstoreParamFileCLI)
|
||||
signingCleanup, err := common.PrepareSigning(&manifestPushOpts.ImagePushOptions, &manifestPushOpts.signing)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user