add Secret<T> to RegistryCredentialConfig

This commit is contained in:
Kyle Matsuda 2023-01-09 17:04:47 -07:00
parent 9e732c6d21
commit e69a18ec79
3 changed files with 35 additions and 24 deletions

View File

@ -30,7 +30,7 @@ use crate::ops;
use crate::ops::Packages;
use crate::sources::{RegistrySource, SourceConfigMap, CRATES_IO_DOMAIN, CRATES_IO_REGISTRY};
use crate::util::auth::{
paserk_public_from_paserk_secret, {self, AuthorizationError},
paserk_public_from_paserk_secret, Secret, {self, AuthorizationError},
};
use crate::util::config::{Config, SslVersionConfig, SslVersionConfigRange};
use crate::util::errors::CargoResult;
@ -45,11 +45,11 @@ use crate::{drop_print, drop_println, version};
pub enum RegistryCredentialConfig {
None,
/// The authentication token.
Token(String),
Token(Secret<String>),
/// Process used for fetching a token.
Process((PathBuf, Vec<String>)),
/// Secret Key and subject for Asymmetric tokens.
AsymmetricKey((String, Option<String>)),
AsymmetricKey((Secret<String>, Option<String>)),
}
impl RegistryCredentialConfig {
@ -71,9 +71,9 @@ impl RegistryCredentialConfig {
pub fn is_asymmetric_key(&self) -> bool {
matches!(self, Self::AsymmetricKey(..))
}
pub fn as_token(&self) -> Option<&str> {
pub fn as_token(&self) -> Option<Secret<&str>> {
if let Self::Token(v) = self {
Some(&*v)
Some(v.as_deref())
} else {
None
}
@ -85,7 +85,7 @@ impl RegistryCredentialConfig {
None
}
}
pub fn as_asymmetric_key(&self) -> Option<&(String, Option<String>)> {
pub fn as_asymmetric_key(&self) -> Option<&(Secret<String>, Option<String>)> {
if let Self::AsymmetricKey(v) = self {
Some(v)
} else {
@ -830,13 +830,13 @@ pub fn registry_login(
}
_ => (None, None),
};
let secret_key: String;
let secret_key: Secret<String>;
if generate_keypair {
assert!(!secret_key_required);
let kp = AsymmetricKeyPair::<pasetors::version3::V3>::generate().unwrap();
let mut key = String::new();
FormatAsPaserk::fmt(&kp.secret, &mut key).unwrap();
secret_key = key;
secret_key = Secret::from(key);
} else if secret_key_required {
assert!(!generate_keypair);
drop_println!(config, "please paste the API secret key below");
@ -846,13 +846,13 @@ pub fn registry_login(
.lock()
.read_line(&mut line)
.with_context(|| "failed to read stdin")?;
secret_key = line.trim().to_string();
secret_key = Secret::from(line.trim().to_string());
} else {
secret_key = old_secret_key
.cloned()
.ok_or_else(|| anyhow!("need a secret_key to set a key_subject"))?;
}
if let Some(p) = paserk_public_from_paserk_secret(&secret_key) {
if let Some(p) = paserk_public_from_paserk_secret(secret_key.as_deref()) {
drop_println!(config, "{}", &p);
} else {
bail!("not a validly formated PASERK secret key");
@ -866,7 +866,7 @@ pub fn registry_login(
));
} else {
new_token = RegistryCredentialConfig::Token(match token {
Some(token) => token.to_string(),
Some(token) => Secret::from(token.to_string()),
None => {
if let Some(login_url) = login_url {
drop_println!(
@ -890,7 +890,7 @@ pub fn registry_login(
.with_context(|| "failed to read stdin")?;
// Automatically remove `cargo login` from an inputted token to
// allow direct pastes from `registry.host()`/me.
line.replace("cargo login", "").trim().to_string()
Secret::from(line.replace("cargo login", "").trim().to_string())
}
});

View File

@ -281,13 +281,13 @@ fn registry_credential_config_inner(
registry
));
}
(Some(token), _, _, _) => RegistryCredentialConfig::Token(token),
(Some(token), _, _, _) => RegistryCredentialConfig::Token(Secret::from(token)),
(_, Some(process), _, _) => RegistryCredentialConfig::Process((
process.path.resolve_program(config),
process.args,
)),
(None, None, Some(key), subject) => {
RegistryCredentialConfig::AsymmetricKey((key, subject))
RegistryCredentialConfig::AsymmetricKey((Secret::from(key), subject))
}
(None, None, None, _) => {
if !is_crates_io {
@ -432,15 +432,19 @@ fn auth_token_optional(
let credential = registry_credential_config(config, sid)?;
let (independent_of_endpoint, token) = match credential {
RegistryCredentialConfig::None => return Ok(None),
RegistryCredentialConfig::Token(config_token) => (true, config_token.to_string()),
RegistryCredentialConfig::Token(config_token) => (true, config_token.expose()),
RegistryCredentialConfig::Process(process) => {
// todo: PASETO with process
run_command(config, &process, sid, Action::Get)?.unwrap()
}
RegistryCredentialConfig::AsymmetricKey((secret_key, secret_key_subject)) => {
let secret: AsymmetricSecretKey<pasetors::version3::V3> =
secret_key.as_str().try_into()?;
let public: AsymmetricPublicKey<pasetors::version3::V3> = (&secret).try_into()?;
let secret: Secret<AsymmetricSecretKey<pasetors::version3::V3>> =
secret_key.map(|key| key.as_str().try_into()).transpose()?;
let public: AsymmetricPublicKey<pasetors::version3::V3> = secret
.as_ref()
.map(|key| key.try_into())
.transpose()?
.expose();
let kip: pasetors::paserk::Id = (&public).try_into()?;
let iat = OffsetDateTime::now_utc();
@ -493,7 +497,7 @@ fn auth_token_optional(
(
false,
pasetors::version3::PublicToken::sign(
&secret,
&secret.expose(),
serde_json::to_string(&message)
.expect("cannot serialize")
.as_bytes(),
@ -598,6 +602,7 @@ pub fn login(config: &Config, sid: &SourceId, token: RegistryCredentialConfig) -
let token = token
.as_token()
.expect("credential_process cannot use login with a secret_key")
.expose()
.to_owned();
run_command(config, &process, sid, Action::Store(token))?;
}
@ -609,9 +614,15 @@ pub fn login(config: &Config, sid: &SourceId, token: RegistryCredentialConfig) -
}
/// Checks that a secret key is valid, and returns the associated public key in Paserk format.
pub(crate) fn paserk_public_from_paserk_secret(secret_key: &str) -> Option<String> {
let secret: AsymmetricSecretKey<pasetors::version3::V3> = secret_key.try_into().ok()?;
let public: AsymmetricPublicKey<pasetors::version3::V3> = (&secret).try_into().ok()?;
pub(crate) fn paserk_public_from_paserk_secret(secret_key: Secret<&str>) -> Option<String> {
let secret: Secret<AsymmetricSecretKey<pasetors::version3::V3>> =
secret_key.map(|key| key.try_into()).transpose().ok()?;
let public: AsymmetricPublicKey<pasetors::version3::V3> = secret
.as_ref()
.map(|key| key.try_into())
.transpose()
.ok()?
.expose();
let mut paserk_pub_key = String::new();
FormatAsPaserk::fmt(&public, &mut paserk_pub_key).unwrap();
Some(paserk_pub_key)

View File

@ -2179,7 +2179,7 @@ pub fn save_credentials(
// login with token
let key = "token".to_string();
let value = ConfigValue::String(token, path_def.clone());
let value = ConfigValue::String(token.expose(), path_def.clone());
let map = HashMap::from([(key, value)]);
let table = CV::Table(map, path_def.clone());
@ -2194,7 +2194,7 @@ pub fn save_credentials(
// login with key
let key = "secret-key".to_string();
let value = ConfigValue::String(secret_key, path_def.clone());
let value = ConfigValue::String(secret_key.expose(), path_def.clone());
let mut map = HashMap::from([(key, value)]);
if let Some(key_subject) = key_subject {
let key = "secret-key-subject".to_string();