-
Notifications
You must be signed in to change notification settings - Fork 227
Open
Labels
proposalEnhancement idea or proposalEnhancement idea or proposal
Description
Proposed change
Currently when using ConnectOptions::with_credentials_file, the passed credentials file will only be loaded once - during the with_credentials_file call - and then never again.
This means when credentials eventually become invalid (e.g. when exp claim in JWT was set), the client not be able to recover.
It is possible to workaround this problem via auth_callback, but it requires pulling a lot of extra dependencies and duplicating code that is already inside the crate:
static USER_CONFIG_RE: Lazy<Regex> = Lazy::new(|| {
Regex::new(r"\s*(?:(?:[-]{3,}.*[-]{3,}\r?\n)([\w\-.=]+)(?:\r?\n[-]{3,}.*[-]{3,}\r?\n))")
.unwrap()
});
fn extract_jwt_and_nkey_from_creds(contents: &str) -> Option<(&str, &str)> {
let mut matches = USER_CONFIG_RE.captures_iter(contents);
let jwt_capture = matches.next()?;
let nkey_capture = matches.next()?;
Some((jwt_capture.get(1)?.as_str(), nkey_capture.get(1)?.as_str()))
}
async fn dynamic_credentials_file_auth(
creds_path: impl AsRef<Path>,
nonce: Vec<u8>,
) -> std::result::Result<Auth, AuthError> {
let contents = read_to_string(creds_path).await.map_err(AuthError::new)?;
let (jwt, nkey) = extract_jwt_and_nkey_from_creds(&contents)
.ok_or_else(|| AuthError::new("creds file not in a valid format"))?;
let kp = KeyPair::from_seed(nkey).map_err(AuthError::new)?;
let signed_nonce = kp.sign(&nonce).map_err(AuthError::new)?;
let mut auth = Auth::new();
auth.jwt = Some(jwt.to_owned());
auth.signature = Some(signed_nonce);
Ok(auth)
}
pub async fn connect_to_nats_refresh() -> Client {
let opts = ConnectOptions::with_auth_callback(move |nonce| {
async move { dynamic_credentials_file_auth("/tmp/nats.creds", nonce).await }
});
opts.connect("nats://localhost:4222").await.unwrap()
}Use case
Allow credential rotation without requiring full application restart.
This is fully supported in other NATS SDKs (at least with the ones I tested: Go, NodeJS, Java and the old non-async Rust crate).
Contribution
No response
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
proposalEnhancement idea or proposalEnhancement idea or proposal