mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-28 11:20:36 +00:00
unstable_cli_options
This commit is contained in:
parent
5939ed0d4f
commit
d8df1425ea
@ -682,7 +682,7 @@ unstable_cli_options!(
|
||||
panic_abort_tests: bool = ("Enable support to run tests with -Cpanic=abort"),
|
||||
host_config: bool = ("Enable the [host] section in the .cargo/config.toml file"),
|
||||
sparse_registry: bool = ("Support plain-HTTP-based crate registries"),
|
||||
registry_auth: bool = ("Authentication for alternative registries"),
|
||||
registry_auth: bool = ("Authentication for alternative registries, and generate registry authentication tokens using asymmetric cryptography"),
|
||||
target_applies_to_host: bool = ("Enable the `target-applies-to-host` key in the .cargo/config.toml file"),
|
||||
rustdoc_map: bool = ("Allow passing external documentation mappings to rustdoc"),
|
||||
separate_nightlies: bool = (HIDDEN),
|
||||
|
@ -44,6 +44,8 @@ pub enum RegistryCredentialConfig {
|
||||
Token(String),
|
||||
/// Process used for fetching a token.
|
||||
Process((PathBuf, Vec<String>)),
|
||||
/// Secret Key and subject for Asymmetric tokens.
|
||||
AsymmetricKey((String, Option<String>)),
|
||||
}
|
||||
|
||||
impl RegistryCredentialConfig {
|
||||
@ -59,6 +61,12 @@ impl RegistryCredentialConfig {
|
||||
pub fn is_token(&self) -> bool {
|
||||
matches!(self, Self::Token(..))
|
||||
}
|
||||
/// Returns `true` if the credential is [`Key`].
|
||||
///
|
||||
/// [`Key`]: Credential::Key
|
||||
pub fn is_asymmetric_key(&self) -> bool {
|
||||
matches!(self, Self::AsymmetricKey(..))
|
||||
}
|
||||
pub fn as_token(&self) -> Option<&str> {
|
||||
if let Self::Token(v) = self {
|
||||
Some(&*v)
|
||||
@ -73,6 +81,13 @@ impl RegistryCredentialConfig {
|
||||
None
|
||||
}
|
||||
}
|
||||
pub fn as_asymmetric_key(&self) -> Option<&(String, Option<String>)> {
|
||||
if let Self::AsymmetricKey(v) = self {
|
||||
Some(v)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PublishOpts<'cfg> {
|
||||
|
@ -26,6 +26,8 @@ pub fn registry_credential_config(
|
||||
index: Option<String>,
|
||||
token: Option<String>,
|
||||
credential_process: Option<config::PathAndArgs>,
|
||||
secret_key: Option<String>,
|
||||
secret_key_subject: Option<String>,
|
||||
#[serde(rename = "default")]
|
||||
_default: Option<String>,
|
||||
}
|
||||
@ -46,26 +48,44 @@ pub fn registry_credential_config(
|
||||
let RegistryConfig {
|
||||
token,
|
||||
credential_process,
|
||||
secret_key,
|
||||
secret_key_subject,
|
||||
..
|
||||
} = config.get::<RegistryConfig>("registry")?;
|
||||
let credential_process =
|
||||
credential_process.filter(|_| config.cli_unstable().credential_process);
|
||||
let secret_key = secret_key.filter(|_| config.cli_unstable().registry_auth);
|
||||
let secret_key_subject = secret_key_subject.filter(|_| config.cli_unstable().registry_auth);
|
||||
|
||||
return Ok(match (token, credential_process) {
|
||||
(Some(_), Some(_)) => {
|
||||
return Err(format_err!(
|
||||
"both `token` and `credential-process` \
|
||||
were specified in the config`.\n\
|
||||
Only one of these values may be set, remove one or the other to proceed.",
|
||||
))
|
||||
}
|
||||
(Some(token), _) => RegistryCredentialConfig::Token(token),
|
||||
(_, Some(process)) => RegistryCredentialConfig::Process((
|
||||
process.path.resolve_program(config),
|
||||
process.args,
|
||||
)),
|
||||
(None, None) => RegistryCredentialConfig::None,
|
||||
});
|
||||
let err_both = |token_key: &str, proc_key: &str| {
|
||||
Err(format_err!(
|
||||
"both `{token_key}` and `{proc_key}` \
|
||||
were specified in the config`.\n\
|
||||
Only one of these values may be set, remove one or the other to proceed.",
|
||||
))
|
||||
};
|
||||
return Ok(
|
||||
match (token, credential_process, secret_key, secret_key_subject) {
|
||||
(Some(_), Some(_), _, _) => return err_both("token", "credential-process"),
|
||||
(Some(_), _, Some(_), _) => return err_both("token", "secret-key"),
|
||||
(_, Some(_), Some(_), _) => return err_both("credential-process", "secret-key"),
|
||||
(_, _, None, Some(_)) => {
|
||||
return Err(format_err!(
|
||||
"`secret-key-subject` was set but `secret-key` was not in the config.\n\
|
||||
Ether set the `secret-key` or remove the `secret-key-subject`."
|
||||
));
|
||||
}
|
||||
(Some(token), _, _, _) => RegistryCredentialConfig::Token(token),
|
||||
(_, Some(process), _, _) => RegistryCredentialConfig::Process((
|
||||
process.path.resolve_program(config),
|
||||
process.args,
|
||||
)),
|
||||
(None, None, Some(key), subject) => {
|
||||
RegistryCredentialConfig::AsymmetricKey((key, subject))
|
||||
}
|
||||
(None, None, None, _) => RegistryCredentialConfig::None,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Find the SourceId's name by its index URL. If environment variables
|
||||
@ -133,52 +153,71 @@ pub fn registry_credential_config(
|
||||
}
|
||||
}
|
||||
|
||||
let (token, credential_process) = if let Some(name) = &name {
|
||||
let (token, credential_process, secret_key, secret_key_subject) = if let Some(name) = &name {
|
||||
log::debug!("found alternative registry name `{name}` for {sid}");
|
||||
let RegistryConfig {
|
||||
token,
|
||||
secret_key,
|
||||
secret_key_subject,
|
||||
credential_process,
|
||||
..
|
||||
} = config.get::<RegistryConfig>(&format!("registries.{name}"))?;
|
||||
let credential_process =
|
||||
credential_process.filter(|_| config.cli_unstable().credential_process);
|
||||
(token, credential_process)
|
||||
let secret_key = secret_key.filter(|_| config.cli_unstable().registry_auth);
|
||||
let secret_key_subject = secret_key_subject.filter(|_| config.cli_unstable().registry_auth);
|
||||
(token, credential_process, secret_key, secret_key_subject)
|
||||
} else {
|
||||
log::debug!("no registry name found for {sid}");
|
||||
(None, None)
|
||||
(None, None, None, None)
|
||||
};
|
||||
|
||||
let name = name.as_deref();
|
||||
Ok(match (token, credential_process) {
|
||||
(Some(_), Some(_)) => {
|
||||
return {
|
||||
Err(format_err!(
|
||||
"both `token` and `credential-process` \
|
||||
were specified in the config for registry `{name}`.\n\
|
||||
Only one of these values may be set, remove one or the other to proceed.",
|
||||
name = name.unwrap()
|
||||
))
|
||||
let err_both = |token_key: &str, proc_key: &str| {
|
||||
Err(format_err!(
|
||||
"both `{token_key}` and `{proc_key}` \
|
||||
were specified in the config for registry `{name}`.\n\
|
||||
Only one of these values may be set, remove one or the other to proceed.",
|
||||
name = name.unwrap()
|
||||
))
|
||||
};
|
||||
Ok(
|
||||
match (token, credential_process, secret_key, secret_key_subject) {
|
||||
(Some(_), Some(_), _, _) => return err_both("token", "credential-process"),
|
||||
(Some(_), _, Some(_), _) => return err_both("token", "secret-key"),
|
||||
(_, Some(_), Some(_), _) => return err_both("credential-process", "secret-key"),
|
||||
(_, _, None, Some(_)) => {
|
||||
return Err(format_err!(
|
||||
"`secret-key-subject` was set but `secret-key` was not in the config \
|
||||
for registry `{}`.\n\
|
||||
Ether set the `secret-key` or remove the `secret-key-subject`.",
|
||||
name.unwrap()
|
||||
));
|
||||
}
|
||||
}
|
||||
(Some(token), _) => RegistryCredentialConfig::Token(token),
|
||||
(_, Some(process)) => {
|
||||
RegistryCredentialConfig::Process((process.path.resolve_program(config), process.args))
|
||||
}
|
||||
(None, None) => {
|
||||
// If we couldn't find a registry-specific credential, try the global credential process.
|
||||
if let Some(process) = config
|
||||
.get::<Option<config::PathAndArgs>>("registry.credential-process")?
|
||||
.filter(|_| config.cli_unstable().credential_process)
|
||||
{
|
||||
RegistryCredentialConfig::Process((
|
||||
process.path.resolve_program(config),
|
||||
process.args,
|
||||
))
|
||||
} else {
|
||||
RegistryCredentialConfig::None
|
||||
(Some(token), _, _, _) => RegistryCredentialConfig::Token(token),
|
||||
(_, Some(process), _, _) => RegistryCredentialConfig::Process((
|
||||
process.path.resolve_program(config),
|
||||
process.args,
|
||||
)),
|
||||
(None, None, Some(key), subject) => {
|
||||
RegistryCredentialConfig::AsymmetricKey((key, subject))
|
||||
}
|
||||
}
|
||||
})
|
||||
(None, None, None, _) => {
|
||||
// If we couldn't find a registry-specific credential, try the global credential process.
|
||||
if let Some(process) = config
|
||||
.get::<Option<config::PathAndArgs>>("registry.credential-process")?
|
||||
.filter(|_| config.cli_unstable().credential_process)
|
||||
{
|
||||
RegistryCredentialConfig::Process((
|
||||
process.path.resolve_program(config),
|
||||
process.args,
|
||||
))
|
||||
} else {
|
||||
RegistryCredentialConfig::None
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@ -288,6 +327,9 @@ fn auth_token_optional(config: &Config, sid: &SourceId) -> CargoResult<Option<St
|
||||
RegistryCredentialConfig::Process(process) => {
|
||||
run_command(config, &process, sid, Action::Get)?.unwrap()
|
||||
}
|
||||
RegistryCredentialConfig::AsymmetricKey((_secret_key, _secret_key_subject)) => {
|
||||
todo!("sign the token")
|
||||
}
|
||||
};
|
||||
|
||||
cache.insert(url.clone(), token.clone());
|
||||
|
@ -1360,6 +1360,26 @@ impl Config {
|
||||
);
|
||||
}
|
||||
|
||||
if toml_v
|
||||
.get("registry")
|
||||
.and_then(|v| v.as_table())
|
||||
.and_then(|t| t.get("secret-key"))
|
||||
.is_some()
|
||||
{
|
||||
bail!(
|
||||
"registry.secret-key cannot be set through --config for security reasons"
|
||||
);
|
||||
} else if let Some((k, _)) = toml_v
|
||||
.get("registries")
|
||||
.and_then(|v| v.as_table())
|
||||
.and_then(|t| t.iter().find(|(_, v)| v.get("secret-key").is_some()))
|
||||
{
|
||||
bail!(
|
||||
"registries.{}.secret-key cannot be set through --config for security reasons",
|
||||
k
|
||||
);
|
||||
}
|
||||
|
||||
CV::from_toml(Definition::Cli(None), toml_v)
|
||||
.with_context(|| format!("failed to convert --config argument `{arg}`"))?
|
||||
};
|
||||
|
@ -435,6 +435,20 @@ fn no_disallowed_values() {
|
||||
config.unwrap_err(),
|
||||
"registries.crates-io.token cannot be set through --config for security reasons",
|
||||
);
|
||||
let config = ConfigBuilder::new()
|
||||
.config_arg("registry.secret-key=\"hello\"")
|
||||
.build_err();
|
||||
assert_error(
|
||||
config.unwrap_err(),
|
||||
"registry.secret-key cannot be set through --config for security reasons",
|
||||
);
|
||||
let config = ConfigBuilder::new()
|
||||
.config_arg("registries.crates-io.secret-key=\"hello\"")
|
||||
.build_err();
|
||||
assert_error(
|
||||
config.unwrap_err(),
|
||||
"registries.crates-io.secret-key cannot be set through --config for security reasons",
|
||||
);
|
||||
}
|
||||
|
||||
#[cargo_test]
|
||||
|
Loading…
x
Reference in New Issue
Block a user