@@ -159,7 +159,7 @@ def _add_shared_instance_options(group: argparse._ArgumentGroup) -> None:
159
159
)
160
160
161
161
162
- def _add_shared_input_options (group : argparse ._ArgumentGroup ) -> None :
162
+ def _add_shared_verify_input_options (group : argparse ._ArgumentGroup ) -> None :
163
163
"""
164
164
Common input options, shared between all `sigstore verify` subcommands.
165
165
"""
@@ -185,6 +185,16 @@ def _add_shared_input_options(group: argparse._ArgumentGroup) -> None:
185
185
default = os .getenv ("SIGSTORE_REKOR_BUNDLE" ),
186
186
help = "The offline Rekor bundle to verify with; not used with multiple inputs" ,
187
187
)
188
+ group .add_argument (
189
+ "--bundle" ,
190
+ metavar = "FILE" ,
191
+ type = Path ,
192
+ default = os .getenv ("SIGSTORE_BUNDLE" ),
193
+ help = (
194
+ "The Sigstore bundle to verify with; not used with multiple inputs; this option is "
195
+ "experimental and may change between releases until stabilized"
196
+ ),
197
+ )
188
198
group .add_argument (
189
199
"files" ,
190
200
metavar = "FILE" ,
@@ -340,6 +350,25 @@ def _parser() -> argparse.ArgumentParser:
340
350
"multiple input files"
341
351
),
342
352
)
353
+ output_options .add_argument (
354
+ "--bundle" ,
355
+ metavar = "FILE" ,
356
+ type = Path ,
357
+ default = os .getenv ("SIGSTORE_BUNDLE" ),
358
+ help = (
359
+ "Write a single Sigstore bundle to the given file; does not work with multiple input "
360
+ "files; this option is experimental and may change between releases until stabilized"
361
+ ),
362
+ )
363
+ output_options .add_argument (
364
+ "--no-bundle" ,
365
+ action = "store_true" ,
366
+ default = False ,
367
+ help = (
368
+ "Don't emit {input}.sigstore files for each input; this option is experimental "
369
+ "and may change between releases until stabilized"
370
+ ),
371
+ )
343
372
output_options .add_argument (
344
373
"--overwrite" ,
345
374
action = "store_true" ,
@@ -387,7 +416,7 @@ def _parser() -> argparse.ArgumentParser:
387
416
formatter_class = argparse .ArgumentDefaultsHelpFormatter ,
388
417
)
389
418
input_options = verify_identity .add_argument_group ("Verification inputs" )
390
- _add_shared_input_options (input_options )
419
+ _add_shared_verify_input_options (input_options )
391
420
392
421
verification_options = verify_identity .add_argument_group ("Verification options" )
393
422
_add_shared_verification_options (verification_options )
@@ -420,7 +449,7 @@ def _parser() -> argparse.ArgumentParser:
420
449
)
421
450
422
451
input_options = verify_github .add_argument_group ("Verification inputs" )
423
- _add_shared_input_options (input_options )
452
+ _add_shared_verify_input_options (input_options )
424
453
425
454
verification_options = verify_github .add_argument_group ("Verification options" )
426
455
_add_shared_verification_options (verification_options )
@@ -556,16 +585,37 @@ def _sign(args: argparse.Namespace) -> None:
556
585
"upcoming release of sigstore-python in favor of Sigstore-style bundles"
557
586
)
558
587
559
- # `--no-default-files` has no effect on `--{signature,certificate,rekor-bundle}`, but we
560
- # forbid it because it indicates user confusion.
588
+ if args .bundle :
589
+ logger .warning (
590
+ "--bundle support is experimental; the behaviour of this flag may change "
591
+ "between releases until stabilized."
592
+ )
593
+
594
+ if args .no_bundle :
595
+ logger .warning (
596
+ "--no-bundle support is experimental; the behaviour of this flag may change "
597
+ "between releases until stabilized."
598
+ )
599
+
600
+ # `--no-default-files` has no effect on `--{signature,certificate,rekor-bundle,bundle}`,
601
+ # but we forbid it because it indicates user confusion.
561
602
if args .no_default_files and (
562
- args .signature or args .certificate or args .rekor_bundle
603
+ args .signature or args .certificate or args .rekor_bundle or args . bundle
563
604
):
564
605
args ._parser .error (
565
606
"--no-default-files may not be combined with --signature, "
566
- "--certificate, or --rekor-bundle" ,
607
+ "--certificate, --rekor-bundle, or - -bundle" ,
567
608
)
568
609
610
+ # Similarly forbid `--rekor-bundle` with `--bundle`, since it again indicates
611
+ # user confusion around outputs.
612
+ if args .rekor_bundle and args .bundle :
613
+ args ._parser .error ("--rekor-bundle may not be combined with --bundle" )
614
+
615
+ # Fail if `--bundle` and `--no-bundle` are both specified.
616
+ if args .bundle and args .no_bundle :
617
+ args ._parser .error ("--bundle may not be combined with --no-bundle" )
618
+
569
619
# Fail if `--signature` or `--certificate` is specified *and* we have more
570
620
# than one input.
571
621
if (args .signature or args .certificate or args .rekor_bundle ) and len (
@@ -583,18 +633,33 @@ def _sign(args: argparse.Namespace) -> None:
583
633
if not file .is_file ():
584
634
args ._parser .error (f"Input must be a file: { file } "
1CF5
)
585
635
586
- sig , cert , bundle = args .signature , args .certificate , args .rekor_bundle
587
- if not sig and not cert and not bundle and not args .no_default_files :
636
+ sig , cert , rekor_bundle , bundle = (
637
+ args .signature ,
638
+ args .certificate ,
639
+ args .rekor_bundle ,
640
+ args .bundle ,
641
+ )
642
+ if (
643
+ not sig
644
+ and not cert
645
+ and not rekor_bundle
646
+ and not bundle
647
+ and not args .no_default_files
648
+ ):
588
649
sig = file .parent / f"{ file .name } .sig"
589
650
cert = file .parent / f"{ file .name } .crt"
590
- bundle = file .parent / f"{ file .name } .rekor"
651
+ rekor_bundle = file .parent / f"{ file .name } .rekor"
652
+ if not args .no_bundle :
653
+ bundle = file .parent / f"{ file .name } .sigstore"
591
654
592
655
if not args .overwrite :
593
656
extants = []
594
657
if sig and sig .exists ():
595
658
extants .append (str (sig ))
596
659
if cert and cert .exists ():
597
660
extants .append (str (cert ))
661
+ if rekor_bundle and rekor_bundle .exists ():
662
+ extants .append (str (rekor_bundle ))
598
663
if bundle and bundle .exists ():
599
664
extants .append (str (bundle ))
600
665
@@ -604,7 +669,12 @@ def _sign(args: argparse.Namespace) -> None:
604
669
f"{ ', ' .join (extants )} "
605
670
)
606
671
607
- output_map [file ] = {"cert" : cert , "sig" : sig , "bundle" : bundle }
672
+ output_map [file ] = {
673
+ "cert" : cert ,
674
+ "sig" : sig ,
675
+ "rekor_bundle" : rekor_bundle ,
676
+ "bundle" : bundle ,
677
+ }
608
678
609
679
# Select the signer to use.
610
680
if args .staging :
@@ -655,7 +725,7 @@ def _sign(args: argparse.Namespace) -> None:
655
725
print (f"Transparency log entry created at index: { result .log_entry .log_index } " )
656
726
657
727
sig_output : TextIO
658
- if outputs ["sig" ]:
728
+ if outputs ["sig" ] is not None :
659
729
sig_output = outputs ["sig" ].open ("w" )
660
730
else :
661
731
sig_output = sys .stdout
@@ -669,11 +739,16 @@ def _sign(args: argparse.Namespace) -> None:
669
739
print (result .cert_pem , file = io )
670
740
print (f"Certificate written to { outputs ['cert' ]} " )
671
741
742
+ if outputs ["rekor_bundle" ] is not None :
743
+ with outputs ["rekor_bundle" ].open (mode = "w" ) as io :
744
+ rekor_bundle = RekorBundle .from_entry (result .log_entry )
745
+ print (rekor_bundle .json (by_alias = True ), file = io )
746
+ print (f"Rekor bundle written to { outputs ['rekor_bundle' ]} " )
747
+
672
748
if outputs ["bundle" ] is not None :
673
749
with outputs ["bundle" ].open (mode = "w" ) as io :
674
- bundle = RekorBundle .from_entry (result .log_entry )
675
- print (bundle .json (by_alias = True ), file = io )
676
- print (f"Rekor bundle written to { outputs ['bundle' ]} " )
750
+ print (result ._to_bundle ().to_json (), file = io )
751
+ print (f"Sigstore bundle written to { outputs ['bundle' ]} " )
677
752
678
753
679
754
def _collect_verification_state (
@@ -687,6 +762,10 @@ def _collect_verification_state(
687
762
purposes) and `materials` is the `VerificationMaterials` to verify with.
688
763
"""
689
764
765
+ # TODO: Allow --bundle during verification. Until then, error.
766
+ if args .bundle :
767
+ args ._parser .error ("--bundle is not supported during verification yet" )
768
+
690
769
# `--rekor-bundle` is a temporary option, pending stabilization of the
691
770
# Sigstore bundle format.
692
771
if args .rekor_bundle :
0 commit comments