Skip to content

Commit 06f4a01

Browse files
wfchandlerahl
andauthored
Read certificate files directly (#1267)
Customers have found it inconvenient and error-prone to pass in the contents of certs and keys to the `certificate create` subcommand. To make this command easier to use, update its `key` and `cert` arguments to be treated as the path to their respective files, rather than their contents. We previously updated the SAML IdP creation command the same way with 11fe44b (Take paths instead of base64 for SAML creation (#1112), 2025-05-28). Co-authored-by: Adam Leventhal <ahl@oxide.computer>
1 parent 3420d09 commit 06f4a01

3 files changed

Lines changed: 40 additions & 6 deletions

File tree

cli/docs/cli.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@
823823
"args": [
824824
{
825825
"long": "cert",
826-
"help": "PEM-formatted string containing public certificate chain"
826+
"help": "path to a PEM-formatted file containing a public certificate chain"
827827
},
828828
{
829829
"long": "description"
@@ -838,7 +838,7 @@
838838
},
839839
{
840840
"long": "key",
841-
"help": "PEM-formatted string containing private key"
841+
"help": "path to a PEM-formatted file containing a private key"
842842
},
843843
{
844844
"long": "name"

cli/src/cli_builder.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,18 +123,31 @@ impl Default for NewCli<'_> {
123123
.arg(
124124
clap::Arg::new("first")
125125
.long("first")
126-
.value_name("ip-addr")
126+
.value_name("IP-ADDR")
127127
.required(true)
128128
.value_parser(clap::value_parser!(std::net::IpAddr)),
129129
)
130130
.arg(
131131
clap::Arg::new("last")
132132
.long("last")
133-
.value_name("ip-addr")
133+
.value_name("IP-ADDR")
134134
.required(true)
135135
.value_parser(clap::value_parser!(std::net::IpAddr)),
136136
),
137137

138+
// We'd like users to provide a file rather than an inline string value for ease of use.
139+
// Update the help string to note we want a file and add a name for the value being
140+
// passed
141+
CliCommand::CertificateCreate => cmd
142+
.mut_arg("cert", |arg| {
143+
arg.value_name("CERT-FILE")
144+
.help("path to a PEM-formatted file containing a public certificate chain")
145+
})
146+
.mut_arg("key", |arg| {
147+
arg.value_name("KEY-FILE")
148+
.help("path to a PEM-formatted file containing a private key")
149+
}),
150+
138151
CliCommand::SamlIdentityProviderCreate => cmd
139152
.mut_arg("json-body", |arg| arg.required(false))
140153
.arg(
@@ -154,14 +167,14 @@ impl Default for NewCli<'_> {
154167
.arg(
155168
clap::Arg::new("private-key")
156169
.long("private-key")
157-
.value_name("key-file")
170+
.value_name("KEY-FILE")
158171
.value_parser(clap::value_parser!(PathBuf))
159172
.help("path to the request signing RSA private key in PKCS#1 DER format"),
160173
)
161174
.arg(
162175
clap::Arg::new("public-cert")
163176
.long("public-cert")
164-
.value_name("cert-file")
177+
.value_name("CERT-FILE")
165178
.value_parser(clap::value_parser!(PathBuf))
166179
.help("path to the request signing public certificate in DER format"),
167180
)

cli/src/main.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,27 @@ impl CliConfig for OxideOverride {
255255
Ok(())
256256
}
257257

258+
fn execute_certificate_create(
259+
&self,
260+
matches: &clap::ArgMatches,
261+
request: &mut oxide::builder::CertificateCreate,
262+
) -> anyhow::Result<()> {
263+
let key_path = matches.get_one::<String>("key").unwrap();
264+
let key_bytes = std::fs::read(key_path)
265+
.with_context(|| format!("failed to read key file {key_path}"))?;
266+
267+
let cert_path = matches.get_one::<String>("cert").unwrap();
268+
let cert_bytes = std::fs::read(cert_path)
269+
.with_context(|| format!("failed to read cert file {cert_path}"))?;
270+
271+
// Note that key and cert will already be set by the generated code,
272+
// but to the path of the files rather than to their contents.
273+
*request = request
274+
.to_owned()
275+
.body_map(|body| body.key(key_bytes).cert(cert_bytes));
276+
Ok(())
277+
}
278+
258279
fn execute_saml_identity_provider_create(
259280
&self,
260281
matches: &clap::ArgMatches,

0 commit comments

Comments
 (0)