auths_cli/commands/artifact/
mod.rs1pub mod core;
2pub mod file;
3pub mod publish;
4pub mod sign;
5pub mod verify;
6
7use clap::{Args, Subcommand};
8use std::path::PathBuf;
9use std::sync::Arc;
10
11use anyhow::Result;
12use auths_core::config::EnvironmentConfig;
13use auths_core::signing::PassphraseProvider;
14
15#[derive(Args, Debug, Clone)]
16#[command(about = "Sign and verify arbitrary artifacts (tarballs, binaries, etc.).")]
17pub struct ArtifactCommand {
18 #[command(subcommand)]
19 pub command: ArtifactSubcommand,
20}
21
22#[derive(Subcommand, Debug, Clone)]
23pub enum ArtifactSubcommand {
24 Sign {
26 #[arg(help = "Path to the artifact file to sign.")]
28 file: PathBuf,
29
30 #[arg(long = "sig-output", value_name = "PATH")]
32 sig_output: Option<PathBuf>,
33
34 #[arg(
36 long,
37 help = "Local alias of the identity key. Omit for device-only CI signing."
38 )]
39 identity_key_alias: Option<String>,
40
41 #[arg(long, help = "Local alias of the device key (used for dual-signing).")]
43 device_key_alias: String,
44
45 #[arg(long, value_name = "N")]
47 expires_in_days: Option<i64>,
48
49 #[arg(long)]
51 note: Option<String>,
52 },
53
54 Publish {
56 #[arg(long)]
58 signature: PathBuf,
59
60 #[arg(long)]
62 package: Option<String>,
63
64 #[arg(long, default_value = "https://auths-registry.fly.dev")]
66 registry: String,
67 },
68
69 Verify {
71 #[arg(help = "Path to the artifact file to verify.")]
73 file: PathBuf,
74
75 #[arg(long, value_name = "PATH")]
77 signature: Option<PathBuf>,
78
79 #[arg(long, value_parser)]
81 identity_bundle: Option<PathBuf>,
82
83 #[arg(long)]
85 witness_receipts: Option<PathBuf>,
86
87 #[arg(long, num_args = 1..)]
89 witness_keys: Vec<String>,
90
91 #[arg(long, default_value = "1")]
93 witness_threshold: usize,
94 },
95}
96
97pub fn handle_artifact(
99 cmd: ArtifactCommand,
100 repo_opt: Option<PathBuf>,
101 passphrase_provider: Arc<dyn PassphraseProvider + Send + Sync>,
102 env_config: &EnvironmentConfig,
103) -> Result<()> {
104 match cmd.command {
105 ArtifactSubcommand::Sign {
106 file,
107 sig_output,
108 identity_key_alias,
109 device_key_alias,
110 expires_in_days,
111 note,
112 } => sign::handle_sign(
113 &file,
114 sig_output,
115 identity_key_alias.as_deref(),
116 &device_key_alias,
117 expires_in_days,
118 note,
119 repo_opt,
120 passphrase_provider,
121 env_config,
122 ),
123 ArtifactSubcommand::Publish {
124 signature,
125 package,
126 registry,
127 } => publish::handle_publish(&signature, package.as_deref(), ®istry),
128 ArtifactSubcommand::Verify {
129 file,
130 signature,
131 identity_bundle,
132 witness_receipts,
133 witness_keys,
134 witness_threshold,
135 } => {
136 let rt = tokio::runtime::Runtime::new()?;
137 rt.block_on(verify::handle_verify(
138 &file,
139 signature,
140 identity_bundle,
141 witness_receipts,
142 &witness_keys,
143 witness_threshold,
144 ))
145 }
146 }
147}
148
149impl crate::commands::executable::ExecutableCommand for ArtifactCommand {
150 fn execute(&self, ctx: &crate::config::CliConfig) -> anyhow::Result<()> {
151 handle_artifact(
152 self.clone(),
153 ctx.repo_path.clone(),
154 ctx.passphrase_provider.clone(),
155 &ctx.env_config,
156 )
157 }
158}