diff --git a/examples/test-svc-acct/src/main.rs b/examples/test-svc-acct/src/main.rs index 1b73a69..bf8f564 100644 --- a/examples/test-svc-acct/src/main.rs +++ b/examples/test-svc-acct/src/main.rs @@ -3,8 +3,11 @@ use yup_oauth2::ServiceAccountAuthenticator; #[tokio::main] async fn main() { - let creds = yup_oauth2::service_account_key_from_file("serviceaccount.json").unwrap(); - let sa = ServiceAccountAuthenticator::builder(creds).build().await.unwrap(); + let creds = yup_oauth2::read_service_account_key("serviceaccount.json").unwrap(); + let sa = ServiceAccountAuthenticator::builder(creds) + .build() + .await + .unwrap(); let scopes = &["https://www.googleapis.com/auth/pubsub"]; let tok = sa.token(scopes).await.unwrap(); diff --git a/src/authenticator.rs b/src/authenticator.rs index b74a3c8..e412862 100644 --- a/src/authenticator.rs +++ b/src/authenticator.rs @@ -134,7 +134,7 @@ impl DeviceFlowAuthenticator { /// Create an authenticator that uses a service account. /// ``` /// # async fn foo() { -/// # let service_account_key = yup_oauth2::service_account_key_from_file("/tmp/foo").unwrap(); +/// # let service_account_key = yup_oauth2::read_service_account_key("/tmp/foo").unwrap(); /// let authenticator = yup_oauth2::ServiceAccountAuthenticator::builder(service_account_key) /// .build() /// .await @@ -358,7 +358,7 @@ impl AuthenticatorBuilder { /// ## Methods available when building a service account authenticator. /// ``` /// # async fn foo() { -/// # let service_account_key = yup_oauth2::service_account_key_from_file("/tmp/foo").unwrap(); +/// # let service_account_key = yup_oauth2::read_service_account_key("/tmp/foo").unwrap(); /// let authenticator = yup_oauth2::ServiceAccountAuthenticator::builder( /// service_account_key, /// ) diff --git a/src/helper.rs b/src/helper.rs index 18cced0..a8f0061 100644 --- a/src/helper.rs +++ b/src/helper.rs @@ -38,10 +38,14 @@ pub fn parse_application_secret>(secret: S) -> io::Result>(path: S) -> io::Result { +pub fn read_service_account_key>(path: P) -> io::Result { let key = std::fs::read_to_string(path)?; - serde_json::from_str(&key) - .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, format!("{}", e))) + serde_json::from_str(&key).map_err(|e| { + io::Error::new( + io::ErrorKind::InvalidData, + format!("Bad service account key: {}", e), + ) + }) } pub(crate) fn join(pieces: &[T], separator: &str) -> String diff --git a/src/service_account.rs b/src/service_account.rs index abb4eda..b9cffaf 100644 --- a/src/service_account.rs +++ b/src/service_account.rs @@ -37,31 +37,29 @@ fn append_base64 + ?Sized>(s: &T, out: &mut String) { /// Decode a PKCS8 formatted RSA key. fn decode_rsa_key(pem_pkcs8: &str) -> Result { - let private = pem_pkcs8.to_string().replace("\\n", "\n").into_bytes(); - let mut private_reader: &[u8] = private.as_ref(); - let private_keys = pemfile::pkcs8_private_keys(&mut private_reader); + let private = pem_pkcs8.replace("\\n", "\n"); + let private_keys = pemfile::pkcs8_private_keys(&mut private.as_bytes()); - if let Ok(pk) = private_keys { - if !pk.is_empty() { - Ok(pk[0].clone()) - } else { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Not enough private keys in PEM", - )) + match private_keys { + Ok(mut keys) if !keys.is_empty() => { + keys.truncate(1); + Ok(keys.remove(0)) } - } else { - Err(io::Error::new( + Ok(_) => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Not enough private keys in PEM", + )), + Err(_) => Err(io::Error::new( io::ErrorKind::InvalidInput, "Error reading key from PEM", - )) + )), } } /// JSON schema of secret service account key. You can obtain the key from /// the Cloud Console at https://console.cloud.google.com/. /// -/// You can use `helpers::service_account_key_from_file()` as a quick way to read a JSON client +/// You can use `helpers::read_service_account_key()` as a quick way to read a JSON client /// secret into a ServiceAccountKey. #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ServiceAccountKey { @@ -248,7 +246,7 @@ impl ServiceAccountFlow { #[cfg(test)] mod tests { use super::*; - use crate::helper::service_account_key_from_file; + use crate::helper::read_service_account_key; use crate::parse_json; use hyper_rustls::HttpsConnector; @@ -333,7 +331,7 @@ mod tests { //#[tokio::test] #[allow(dead_code)] async fn test_service_account_e2e() { - let key = service_account_key_from_file(&TEST_PRIVATE_KEY_PATH.to_string()).unwrap(); + let key = read_service_account_key(&TEST_PRIVATE_KEY_PATH.to_string()).unwrap(); let acc = ServiceAccountFlow::new(ServiceAccountFlowOpts { key, subject: None }).unwrap(); let https = HttpsConnector::new(); let client = hyper::Client::builder() @@ -348,7 +346,7 @@ mod tests { #[test] fn test_jwt_initialize_claims() { - let key = service_account_key_from_file(TEST_PRIVATE_KEY_PATH).unwrap(); + let key = read_service_account_key(TEST_PRIVATE_KEY_PATH).unwrap(); let scopes = vec!["scope1", "scope2", "scope3"]; let claims = Claims::new(&key, &scopes, None); @@ -368,7 +366,7 @@ mod tests { #[test] fn test_jwt_sign() { - let key = service_account_key_from_file(TEST_PRIVATE_KEY_PATH).unwrap(); + let key = read_service_account_key(TEST_PRIVATE_KEY_PATH).unwrap(); let scopes = vec!["scope1", "scope2", "scope3"]; let signer = JWTSigner::new(&key.private_key).unwrap(); let claims = Claims::new(&key, &scopes, None);