feat: use constant format challenge TXT key

This commit is contained in:
Aravinth Manivannan 2022-05-19 16:24:18 +05:30
parent 2d07f7f0ca
commit a2582fdce8

View file

@ -19,12 +19,14 @@ use trust_dns_resolver::{
config::{ResolverConfig, ResolverOpts}, config::{ResolverConfig, ResolverOpts},
AsyncResolver, AsyncResolver,
}; };
use lazy_static::lazy_static;
use crate::utils::get_random; use crate::utils::get_random;
use crate::ArcCtx;
pub struct TXTChallenge { pub struct TXTChallenge {
key: String, key: String,
base_hostname: String, _base_hostname: String,
value: String, value: String,
} }
@ -32,54 +34,65 @@ const KEY_LEN: usize = 30;
const VALUES_LEN: usize = 30; const VALUES_LEN: usize = 30;
impl TXTChallenge { impl TXTChallenge {
pub async fn new(hostname: &str) -> Self { pub fn get_challenge_txt_key_prefix(ctx: &ArcCtx) -> String {
let key = get_random(KEY_LEN); // starchart-{{ starchart instance's hostname}}.{{ forge instance's hostname }}
format!("starchart-{}", &ctx.settings.server.domain)
}
pub fn get_challenge_txt_key(ctx: &ArcCtx, hostname: &str) -> String {
format!("{}.{}", Self::get_challenge_txt_key_prefix(ctx), hostname)
}
pub async fn new(ctx: &ArcCtx, hostname: &str) -> Self {
let key = Self::get_challenge_txt_key(ctx, hostname);
let value = get_random(VALUES_LEN); let value = get_random(VALUES_LEN);
Self { Self {
key, key,
value, value,
base_hostname: hostname.to_string(), _base_hostname: hostname.to_string(),
} }
} }
pub fn get_txt_key(&self) -> String { pub async fn verify_txt(&self) -> Result<bool, Box<dyn std::error::Error>> {
format!("{}.{}", self.key, self.base_hostname)
}
pub async fn verify_txt(&self) -> bool {
let conf = ResolverConfig::cloudflare_tls(); let conf = ResolverConfig::cloudflare_tls();
let opts = ResolverOpts::default(); let opts = ResolverOpts::default();
let resolver = AsyncResolver::tokio(conf, opts).unwrap(); let resolver = AsyncResolver::tokio(conf, opts)?;
let res = resolver.txt_lookup(&self.get_txt_key()).await.unwrap(); let res = resolver.txt_lookup(&self.key).await?;
res.iter().any(|r| r.to_string() == self.value) Ok(res.iter().any(|r| r.to_string() == self.value))
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::tests::sqlx_sqlite;
#[actix_rt::test] #[actix_rt::test]
async fn verify_txt_works() { async fn verify_txt_works() {
// please note that this DNS record is in prod // please note that this DNS record is in prod
const KEY: &str = "test-starchart-foobardontmindme"; const BASE_DOMAIN: &str = "forge.forgeflux.org";
const BASE_DOMAIN: &str = "starchart.forgeflux.org";
const VALUE: &str = "ifthisvalueisretrievedbyforgefluxstarchartthenthetestshouldpass"; const VALUE: &str = "ifthisvalueisretrievedbyforgefluxstarchartthenthetestshouldpass";
let (_db, ctx, _federate, _tmp_dir) = sqlx_sqlite::get_ctx().await;
let key = TXTChallenge::get_challenge_txt_key(&ctx, BASE_DOMAIN);
let mut txt_challenge = TXTChallenge { let mut txt_challenge = TXTChallenge {
value: VALUE.to_string(), value: VALUE.to_string(),
base_hostname: BASE_DOMAIN.to_string(), _base_hostname: BASE_DOMAIN.to_string(),
key: KEY.to_string(), key: key.clone(),
}; };
assert_eq!( assert_eq!(
txt_challenge.get_txt_key(), TXTChallenge::get_challenge_txt_key(&ctx, BASE_DOMAIN),
"test-starchart-foobardontmindme.starchart.forgeflux.org" key,
); );
assert!( assert!(
txt_challenge.verify_txt().await, txt_challenge.verify_txt().await.unwrap(),
"TXT Challenge verification test" "TXT Challenge verification test"
); );
txt_challenge.value = KEY.into(); txt_challenge.value = key;
assert!(!txt_challenge.verify_txt().await); assert!(!txt_challenge.verify_txt().await.unwrap());
} }
} }