Skip to content

Commit 521cd86

Browse files
committed
impl(auth): replace unmaintained rustls-pemfile with rustls-pki-types for private key handling
1 parent d0589a4 commit 521cd86

4 files changed

Lines changed: 43 additions & 40 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ prost-types = { default-features = false, version = "0.14" }
328328
rand = { default-features = false, version = "0.9.2" }
329329
reqwest = { default-features = false, version = "0.12.24", features = ["json"] }
330330
rustls = { default-features = false, version = "0.23" }
331-
rustls-pemfile = { default-features = false, version = "2" }
331+
rustls-pki-types = { default-features = false, version = "1.13" }
332332
semver = { default-features = false, version = "1.0.21" }
333333
serde = { default-features = false, version = "1.0.228", features = ["serde_derive"] }
334334
serde_json = { default-features = false, version = "1.0.132", features = ["std"] }

src/auth/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ bytes.workspace = true
4040
http.workspace = true
4141
reqwest = { workspace = true, features = ["json", "rustls-tls"] }
4242
rustls = { workspace = true, features = ["logging", "ring", "std", "tls12"] }
43-
rustls-pemfile = { workspace = true, features = ["std"] }
43+
rustls-pki-types = { workspace = true, features = ["std"] }
4444
serde.workspace = true
4545
serde_json.workspace = true
4646
thiserror.workspace = true

src/auth/src/credentials/service_account.rs

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ use crate::build_errors::Error as BuilderError;
7676
use crate::constants::DEFAULT_SCOPE;
7777
use crate::credentials::dynamic::{AccessTokenCredentialsProvider, CredentialsProvider};
7878
use crate::credentials::{AccessToken, AccessTokenCredentials, CacheableResource, Credentials};
79-
use crate::errors::{self, CredentialsError};
79+
use crate::errors::{self};
8080
use crate::headers_util::build_cacheable_headers;
8181
use crate::token::{CachedTokenProvider, Token, TokenProvider};
8282
use crate::token_cache::TokenCache;
@@ -86,7 +86,7 @@ use http::{Extensions, HeaderMap};
8686
use jws::{CLOCK_SKEW_FUDGE, DEFAULT_TOKEN_TIMEOUT, JwsClaims, JwsHeader};
8787
use rustls::crypto::CryptoProvider;
8888
use rustls::sign::Signer;
89-
use rustls_pemfile::Item;
89+
use rustls_pki_types::{PrivateKeyDer, pem::PemObject};
9090
use serde_json::Value;
9191
use std::sync::Arc;
9292
use time::OffsetDateTime;
@@ -377,26 +377,31 @@ impl ServiceAccountKey {
377377
|p| p.key_provider,
378378
);
379379

380-
let private_key = rustls_pemfile::read_one(&mut private_key.as_bytes())
381-
.map_err(errors::non_retryable)?
382-
.ok_or_else(|| {
383-
errors::non_retryable_from_str("missing PEM section in service account key")
384-
})?;
385-
let pk = match private_key {
386-
Item::Pkcs8Key(item) => key_provider.load_private_key(item.into()),
387-
other => {
388-
return Err(Self::unexpected_private_key_error(other));
380+
let key_der = PrivateKeyDer::from_pem_slice(private_key.as_bytes()).map_err(|e| {
381+
errors::non_retryable_from_str(format!(
382+
"Failed to parse service account private key PEM: {}",
383+
e
384+
))
385+
})?;
386+
387+
let pkcs8_der = match key_der {
388+
PrivateKeyDer::Pkcs8(der) => der,
389+
_ => {
390+
return Err(errors::non_retryable_from_str(format!(
391+
"expected key to be in form of PKCS8, found {:?}",
392+
key_der
393+
)));
389394
}
390395
};
391-
let sk = pk.map_err(errors::non_retryable)?;
392-
sk.choose_scheme(&[rustls::SignatureScheme::RSA_PKCS1_SHA256])
393-
.ok_or_else(|| errors::non_retryable_from_str("Unable to choose RSA_PKCS1_SHA256 signing scheme as it is not supported by current signer"))
394-
}
395396

396-
fn unexpected_private_key_error(private_key_format: Item) -> CredentialsError {
397-
errors::non_retryable_from_str(format!(
398-
"expected key to be in form of PKCS8, found {private_key_format:?}",
399-
))
397+
let pk = key_provider
398+
.load_private_key(PrivateKeyDer::Pkcs8(pkcs8_der))
399+
.map_err(errors::non_retryable)?;
400+
401+
pk.choose_scheme(&[rustls::SignatureScheme::RSA_PKCS1_SHA256])
402+
.ok_or_else(||{
403+
errors::non_retryable_from_str("Unable to choose RSA_PKCS1_SHA256 signing scheme as it is not supported by current signer")
404+
})
400405
}
401406
}
402407

@@ -557,7 +562,6 @@ mod tests {
557562
use http::header::AUTHORIZATION;
558563
use rsa::pkcs1::EncodeRsaPrivateKey;
559564
use rsa::pkcs8::LineEnding;
560-
use rustls_pemfile::Item;
561565
use serde_json::Value;
562566
use serde_json::json;
563567
use std::error::Error as _;
@@ -706,7 +710,7 @@ mod tests {
706710

707711
service_account_key["private_key"] = Value::from(key);
708712
let cred = Builder::new(service_account_key).build()?;
709-
let expected_error_message = "expected key to be in form of PKCS8, found Pkcs1Key";
713+
let expected_error_message = "expected key to be in form of PKCS8, found ";
710714
assert!(
711715
cred.headers(Extensions::new())
712716
.await
@@ -821,20 +825,28 @@ mod tests {
821825
};
822826

823827
let signer = tg.service_account_key.signer();
824-
let expected_error_message = "missing PEM section in service account key";
828+
let expected_error_message = "Failed to parse service account private key PEM";
825829
assert!(signer.is_err_and(|e| e.to_string().contains(expected_error_message)));
826830
Ok(())
827831
}
828832

829833
#[test]
830-
fn unexpected_private_key_error_message() -> TestResult {
831-
let expected_message = format!(
832-
"expected key to be in form of PKCS8, found {:?}",
833-
Item::Crl(Vec::new().into()) // Example unsupported key type
834+
fn signer_fails_on_invalid_pem_type() -> TestResult {
835+
let invalid_pem = concat!(
836+
"-----BEGI X509 CRL-----\n",
837+
"MIIBmzCBja... (truncated) ...\n",
838+
"-----END X509 CRL-----"
834839
);
835840

836-
let error = ServiceAccountKey::unexpected_private_key_error(Item::Crl(Vec::new().into()));
837-
assert!(error.to_string().contains(&expected_message));
841+
let mut key = ServiceAccountKey {
842+
private_key: invalid_pem.to_string(),
843+
..Default::default()
844+
};
845+
key.private_key = invalid_pem.to_string();
846+
let result = key.signer();
847+
assert!(result.is_err());
848+
let error_msg = result.unwrap_err().to_string();
849+
assert!(error_msg.contains("Failed to parse service account private key PEM"));
838850
Ok(())
839851
}
840852

0 commit comments

Comments
 (0)