Skip to content

Commit

Permalink
refactor: replace time with chrono crate
Browse files Browse the repository at this point in the history
  • Loading branch information
mibmo committed Jul 4, 2023
1 parent c7e7b92 commit d7a2a84
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 46 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ serde_derive = "1"
serde_json = "1"
openssl = "0"
base64 = "0"
time = "=0.1.45" # same version as acme-lib uses
acme-lib = { git = 'https://github.com/DBCDK/acme-lib', branch = 'add-sans-individually' }
regex = "1"
lazy_static = "1"
Expand Down
55 changes: 34 additions & 21 deletions src/common.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extern crate openssl;
extern crate regex;

use self::openssl::asn1::Asn1TimeRef;
use self::openssl::asn1::{Asn1Time, Asn1TimeRef};
use self::openssl::nid::Nid;
use self::openssl::x509::{X509NameEntryRef, X509};

Expand All @@ -20,6 +20,7 @@ use std::collections::HashSet;
use std::convert::TryFrom;
use std::fmt::Formatter;
use std::path::PathBuf;
use chrono::{TimeZone, Utc};
pub type CertName = String;

#[derive(Debug, Clone, Serialize)]
Expand Down Expand Up @@ -199,12 +200,17 @@ impl std::convert::From<KubeError> for PersistError {
}
}

pub enum TimeError {
Diff(openssl::error::ErrorStack),
UnixTimestampOutOfBounds,
}

#[derive(Debug, Clone)]
pub struct Cert {
pub cn: String,
pub sans: HashSet<String>,
pub valid_from: time::Tm, // always utc
pub valid_to: time::Tm // always utc
pub valid_from: chrono::DateTime<Utc>,
pub valid_to: chrono::DateTime<Utc>,
}

impl Cert {
Expand Down Expand Up @@ -256,18 +262,24 @@ impl Cert {
}
}

// #cryhard rust openssl lib doesn't allow for a plain convertion from ASN-time to time::Tm or any
// other rustlang time type. :( So... We to_string the ASNTime and re-parse it and hope for the best
fn get_timestamp(time_ref: &Asn1TimeRef) -> Result<time::Tm, time::ParseError> {
const IN_FORMAT: &str = "%b %e %H:%M:%S %Y %Z"; // May 31 15:21:16 2020 GMT
time::strptime(&format!("{}", &time_ref), IN_FORMAT)
fn get_timestamp(time_ref: &Asn1TimeRef) -> Result<chrono::DateTime<Utc>, TimeError> {
let epoch = Asn1Time::from_unix(0).expect("Failed to create Asn1Time at unix epoch");
let diff = epoch.diff(&time_ref).map_err(TimeError::Diff)?;
//let diff = time_ref.diff(&epoch).map_err(TimeError::Diff)?;
let unix_ts = diff.days as i64 * (24 * 60 * 60) + diff.secs as i64;
use chrono::offset::LocalResult;
match chrono::Utc.timestamp_opt(unix_ts.into(), 0) {
LocalResult::None => Err(TimeError::UnixTimestampOutOfBounds),
LocalResult::Single(datetime) => Ok(datetime),
LocalResult::Ambiguous(_, _) => unreachable!("timestamp_opt never returns LocalResult::Ambigious"),
}
}

pub fn state(&self, config: &FaytheConfig, spec: &CertSpec) -> CertState {
let now = time::now_utc();
let now = Utc::now();
let state = match self.valid_to {
to if now > to => CertState::Expired,
to if now + time::Duration::days(config.renewal_threshold as i64) > to => CertState::ExpiresSoon,
to if now + chrono::Duration::days(config.renewal_threshold as i64) > to => CertState::ExpiresSoon,
_ if now < self.valid_from => CertState::NotYetValid,
to if now >= self.valid_from && now <= to => CertState::Valid,
_ => CertState::Unknown,
Expand Down Expand Up @@ -369,8 +381,8 @@ impl std::convert::From<SpecError> for TouchError {
}
}

impl std::convert::From<time::ParseError> for CertState {
fn from(_: time::ParseError) -> Self {
impl std::convert::From<TimeError> for CertState {
fn from(_: TimeError) -> Self {
CertState::ParseError
}
}
Expand All @@ -385,6 +397,7 @@ pub mod tests {
use crate::set;
use super::DNSName;
use crate::config::{KubeMonitorConfig, FileMonitorConfig, MonitorConfig};
use chrono::DateTime;

const TIME_FORMAT: &str = "%Y-%m-%dT%H:%M:%S%z"; // 2019-10-09T11:50:22+0200

Expand Down Expand Up @@ -487,7 +500,7 @@ pub mod tests {
Ingress{
name: "test".to_string(),
namespace: "test".to_string(),
touched: time::empty_tm(),
touched: DateTime::<Utc>::MIN_UTC,
hosts: [host.to_string()].to_vec(),
}
}
Expand Down Expand Up @@ -518,8 +531,8 @@ pub mod tests {
Not Before: Dec 1 11:42:07 2020 GMT
Not After : Nov 24 11:42:07 2050 GMT
*/
assert_eq!(cert.valid_from, time::strptime("2020-12-01T11:42:07+0000", TIME_FORMAT).unwrap());
assert_eq!(cert.valid_to, time::strptime("2050-11-24T11:42:07+0000", TIME_FORMAT).unwrap());
assert_eq!(cert.valid_from, DateTime::parse_from_str("2020-12-01T11:42:07+0000", TIME_FORMAT).unwrap());
assert_eq!(cert.valid_to, DateTime::parse_from_str("2050-11-24T11:42:07+0000", TIME_FORMAT).unwrap());

let config = create_test_kubernetes_config(false).faythe_config;
let spec = create_test_certspec(cn, sans);
Expand All @@ -540,8 +553,8 @@ pub mod tests {
Not Before: Dec 1 11:42:07 2020 GMT
Not After : Nov 24 11:42:07 2050 GMT
*/
assert_eq!(cert.valid_from, time::strptime("2020-12-01T11:42:07+0000", TIME_FORMAT).unwrap());
assert_eq!(cert.valid_to, time::strptime("2050-11-24T11:42:07+0000", TIME_FORMAT).unwrap());
assert_eq!(cert.valid_from, DateTime::parse_from_str("2020-12-01T11:42:07+0000", TIME_FORMAT).unwrap());
assert_eq!(cert.valid_to, DateTime::parse_from_str("2050-11-24T11:42:07+0000", TIME_FORMAT).unwrap());

let config = create_test_kubernetes_config(false).faythe_config;
let spec = create_test_certspec(cn, sans);
Expand All @@ -559,8 +572,8 @@ pub mod tests {
Not Before: Dec 1 11:42:07 2020 GMT
Not After : Nov 24 11:42:07 2050 GMT
*/
assert_eq!(cert.valid_from, time::strptime("2020-12-01T11:42:07+0000", TIME_FORMAT).unwrap());
assert_eq!(cert.valid_to, time::strptime("2050-11-24T11:42:07+0000", TIME_FORMAT).unwrap());
assert_eq!(cert.valid_from, DateTime::parse_from_str("2020-12-01T11:42:07+0000", TIME_FORMAT).unwrap());
assert_eq!(cert.valid_to, DateTime::parse_from_str("2050-11-24T11:42:07+0000", TIME_FORMAT).unwrap());

let cn = "cn.longlived";
let sans = set![cn, "san1.longlived", "san2.shortlived"];
Expand Down Expand Up @@ -610,8 +623,8 @@ pub mod tests {
Not Before: Dec 1 11:41:19 2020 GMT
Not After : Dec 2 11:41:19 2020 GMT
*/
assert_eq!(cert.valid_from, time::strptime("2020-12-01T11:41:19+0000", TIME_FORMAT).unwrap());
assert_eq!(cert.valid_to, time::strptime("2020-12-02T11:41:19+0000", TIME_FORMAT).unwrap());
assert_eq!(cert.valid_from, DateTime::parse_from_str("2020-12-01T11:41:19+0000", TIME_FORMAT).unwrap());
assert_eq!(cert.valid_to, DateTime::parse_from_str("2020-12-02T11:41:19+0000", TIME_FORMAT).unwrap());

let config = create_test_kubernetes_config(false).faythe_config;
let spec = create_test_certspec(cn, sans);
Expand Down
1 change: 0 additions & 1 deletion src/file.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
extern crate time;
extern crate walkdir;


Expand Down
8 changes: 5 additions & 3 deletions src/issuer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ use crate::dns::DNSError;
use crate::metrics;
use crate::metrics::MetricsType;

use chrono::Utc;

pub fn process(faythe_config: FaytheConfig, rx: Receiver<CertSpec>) {

let mut queue: VecDeque<IssueOrder> = VecDeque::new();
Expand Down Expand Up @@ -82,7 +84,7 @@ fn check_queue(queue: &mut VecDeque<IssueOrder>) -> Result<(), IssuerError> {
IssuerError::DNS(dns::DNSError::WrongAnswer(domain)) => {
log::data("Wrong DNS answer", &domain);
// Retry for two hours. Propagation on gratisdns is pretty slow.
if time::now_utc() < order.challenge_time + time::Duration::minutes(120) {
if Utc::now() < order.challenge_time + chrono::Duration::minutes(120) {
queue.push_back(order);
} else {
log::data("giving up validating dns challenge for spec", &order.spec);
Expand Down Expand Up @@ -169,7 +171,7 @@ fn setup_challenge(config: &FaytheConfig, spec: &CertSpec) -> Result<IssueOrder,
spec: spec.clone(),
authorizations,
inner: ord_new,
challenge_time: time::now_utc(),
challenge_time: Utc::now(),
auth_dns_servers,
val_dns_servers,
})
Expand All @@ -179,7 +181,7 @@ struct IssueOrder {
spec: CertSpec,
inner: NewOrder<MemoryPersist>,
authorizations: Vec<Auth<MemoryPersist>>,
challenge_time: time::Tm,
challenge_time: chrono::DateTime<Utc>,
auth_dns_servers: HashSet<String>,
val_dns_servers: HashSet<String>,
}
Expand Down
26 changes: 13 additions & 13 deletions src/kube.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
extern crate serde;
extern crate serde_json;
extern crate base64;
extern crate time;

use serde_json::{Value};
use serde_json::json;
Expand All @@ -22,12 +21,14 @@ use acme_lib::Certificate;

use base64::Engine;

use chrono::Utc;

#[derive(Debug, Clone)]
pub struct Ingress {
pub name: String,
pub namespace: String,
pub hosts: Vec<String>,
pub touched: time::Tm,
pub touched: chrono::DateTime<Utc>,
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -77,7 +78,7 @@ pub fn get_ingresses(config: &KubeMonitorConfig) -> Result<Vec<Ingress>, KubeErr
let rules = vec(&i["spec"]["rules"])?;
let touched = match &config.touch_annotation {
Some(a) => tm(i["metadata"]["annotations"].get(&a)),
None => time::empty_tm()
None => chrono::DateTime::<Utc>::MIN_UTC,
};
ingresses.push(Ingress{
name: sr(&i["metadata"]["name"])?,
Expand Down Expand Up @@ -135,12 +136,12 @@ fn sr(subject: &Value) -> Result<String, KubeError> {
}
}

fn tm(subject: Option<&Value>) -> time::Tm {
fn tm(subject: Option<&Value>) -> chrono::DateTime<Utc> {
let a = subject.and_then(|s| s.as_str());
match a {
// assume "now" if there is something non-parsable in there
Some(a) => time::strptime(&a, self::TIME_FORMAT).unwrap_or(time::now_utc()),
_ => time::empty_tm()
Some(a) => chrono::DateTime::parse_from_str(&a, self::TIME_FORMAT).map(std::convert::Into::into).unwrap_or(Utc::now()),
_ => chrono::DateTime::<Utc>::MIN_UTC,
}
}

Expand Down Expand Up @@ -261,14 +262,13 @@ impl CertSpecable for Ingress {
fn touch(&self, config: &ConfigContainer) -> Result<(), TouchError> {
let monitor_config = config.get_kube_monitor_config()?;
match &monitor_config.touch_annotation {
Some(a) => Ok(self.annotate(&a,
&time::strftime(TIME_FORMAT, &time::now_utc())?)?),
Some(a) => Ok(self.annotate(&a, &Utc::now().format(TIME_FORMAT).to_string())?),
None => Ok(())
}
}

fn should_retry(&self, config: &ConfigContainer) -> bool {
time::now_utc() > self.touched + time::Duration::milliseconds(config.faythe_config.issue_grace as i64)
Utc::now() > self.touched + chrono::Duration::milliseconds(config.faythe_config.issue_grace as i64)
}
}

Expand Down Expand Up @@ -303,15 +303,15 @@ impl std::convert::From<base64::DecodeError> for KubeError {
KubeError::Format
}
}
impl std::convert::From<time::ParseError> for KubeError {
fn from(err: time::ParseError) -> Self {
impl std::convert::From<chrono::ParseError> for KubeError {
fn from(err: chrono::ParseError) -> Self {
log::error("Failed to parse timestamp", &err);
KubeError::Format
}
}

impl std::convert::From<time::ParseError> for TouchError {
fn from(_err: time::ParseError) -> Self {
impl std::convert::From<chrono::ParseError> for TouchError {
fn from(_err: chrono::ParseError) -> Self {
TouchError::Failed
}
}
Expand Down
11 changes: 5 additions & 6 deletions src/monitor.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
extern crate time;

use std::thread;
use std::time::Duration;

Expand All @@ -24,6 +22,8 @@ use std::prelude::v1::Vec;
use crate::metrics;
use crate::metrics::MetricsType;

use chrono::Utc;

pub fn monitor_k8s(config: ConfigContainer, tx: Sender<CertSpec>) {
log::info("k8s monitoring-started");
let monitor_config = config.get_kube_monitor_config().unwrap();
Expand Down Expand Up @@ -131,7 +131,6 @@ mod tests {
use crate::mpsc;
use crate::mpsc::{Receiver, Sender};
use std::collections::HashSet;
use std::ops::Add;

fn create_channel() -> (Sender<CertSpec>, Receiver<CertSpec>) {
mpsc::channel()
Expand All @@ -141,7 +140,7 @@ mod tests {
[Ingress {
name: "test".to_string(),
namespace: "test".to_string(),
touched: time::empty_tm(),
touched: chrono::DateTime::<Utc>::MIN_UTC,
hosts: [host.clone()].to_vec(),
}]
.to_vec()
Expand All @@ -156,8 +155,8 @@ mod tests {
cert: Cert {
cn: host.clone(),
sans,
valid_from: time::now_utc(),
valid_to: time::now_utc().add(time::Duration::days(valid_days)),
valid_from: Utc::now(),
valid_to: Utc::now() + chrono::Duration::days(valid_days),
},
key: vec![],
}
Expand Down

0 comments on commit d7a2a84

Please sign in to comment.