38
38
from sigstore ._internal .fulcio .client import ExpiredCertificate
39
39
from sigstore ._internal .rekor import _hashedrekord_from_parts
40
40
from sigstore ._internal .rekor .client import RekorClient
41
+ from sigstore ._internal .tuf import TrustUpdater
41
42
from sigstore ._utils import sha256_digest
42
43
from sigstore .dsse import StatementBuilder , Subject
43
44
from sigstore .dsse ._predicate import (
@@ -263,7 +264,13 @@ def _parser() -> argparse.ArgumentParser:
263
264
"--staging" ,
264
265
action = "store_true" ,
265
266
default = _boolify_env ("SIGSTORE_STAGING" ),
266
- help = "Use sigstore's staging instances, instead of the default production instances" ,
267
+ help = "Use sigstore's staging instance, instead of the default production instance" ,
268
+ )
269
+ global_instance_options .add_argument (
270
+ "--instance" ,
271
+ metavar = "URL" ,
272
+ type = str ,
273
+ help = "Use a given Sigstore instance URL, instead of the default production instance" ,
267
274
)
268
275
global_instance_options .add_argument (
269
276
"--trust-config" ,
@@ -545,6 +552,20 @@ def _parser() -> argparse.ArgumentParser:
545
552
)
546
553
_add_shared_oidc_options (get_identity_token )
547
554
555
+ # `sigstore init-instance`
556
+ init_instance = subcommands .add_parser (
557
+ "init-instance" ,
558
+ help = "Initialize trust for a Sigstore instance" ,
559
+ formatter_class = argparse .ArgumentDefaultsHelpFormatter ,
560
+ parents = [parent_parser ],
561
+ )
562
+ init_instance .add_argument (
563
+ "root" ,
564
+ metavar = "ROOT" ,
565
+ type = Path ,
566
+ help = "The TUF root metadata for the instance" ,
567
+ )
568
+
548
569
# `sigstore plumbing`
549
570
plumbing = subcommands .add_parser (
550
571
"plumbing" ,
@@ -626,6 +647,8 @@ def main(args: list[str] | None = None) -> None:
626
647
_verify_github (args )
627
648
elif args .subcommand == "get-identity-token" :
628
649
_get_identity_token (args )
650
+ elif args .subcommand == "init-instance" :
651
+ _init_instance (args )
629
652
elif args .subcommand == "plumbing" :
630
653
if args .plumbing_subcommand == "fix-bundle" :
631
654
_fix_bundle (args )
@@ -636,6 +659,24 @@ def main(args: list[str] | None = None) -> None:
636
659
except Error as e :
637
660
e .log_and_exit (_logger , args .verbose >= 1 )
638
661
662
+ def _init_instance (args : argparse .Namespace ) -> None :
663
+ """
664
+ Initialize trust for a Sigstore instance
665
+ """
666
+ root : Path = args .root
667
+ instance : str | None = args .instance
668
+ if not root .is_file ():
669
+ _invalid_arguments (args , f"Input must be a file: { root } " )
670
+ if instance is None :
671
+ _invalid_arguments (args , "init-instance requires '--instance URL'" )
672
+
673
+ try :
674
+ TrustUpdater .trust_instance (instance , root )
675
+ except ValueError as e :
676
+ # instance is already configured
677
+ _logger .warning (e )
678
+
679
+
639
680
640
681
def _get_identity_token (args : argparse .Namespace ) -> None :
641
682
"""
@@ -1210,13 +1251,18 @@ def _get_trust_config(args: argparse.Namespace) -> ClientTrustConfig:
1210
1251
Return the client trust configuration (Sigstore service URLs, key material and lifetimes)
1211
1252
1212
1253
The configuration may come from explicit argument (--trust-config) or from the TUF
1213
- repository of the used Sigstore instance.
1254
+ repository of the used Sigstore instance (--staging or --instance) .
1214
1255
"""
1215
1256
# Not all commands provide --offline
1216
1257
offline = getattr (args , "offline" , False )
1217
1258
1218
1259
if args .trust_config :
1219
1260
trust_config = ClientTrustConfig .from_json (args .trust_config .read_text ())
1261
+ elif args .instance :
1262
+ try :
1263
+ trust_config = ClientTrustConfig .from_tuf (args .instance , offline = offline )
1264
+ except FileNotFoundError :
1265
+ raise ValueError (f"Instance { args .instance } trust seems to not be initialized." )
1220
1266
elif args .staging :
1221
1267
trust_config = ClientTrustConfig .staging (offline = offline )
1222
1268
else :
0 commit comments