Skip to content

Commit

Permalink
Removes chrono and usages of DateTime<Utc> and replaces them with…
Browse files Browse the repository at this point in the history
…`time::OffsetDateTime`.

This change should not have any semantic meaning and is being done to address RUSTSEC-2020-0071 (see #244) and RUSTSEC-20200159 (see #245).

This is a breaking API change because some result types include create/updated timestamps. Consumers of the library will need to add a direct dependency on `time`. Note that `chrono` already uses `time` internally, so this change should not bloat transitive dependencies.

For those needing serialization support of  `OffsetDateTime` timestamps, the `time` crate offers this support with the `serde` feature flag.

One small point of friction here is rfc3339 support. `time` has this support on [a branch](time-rs/time#387) that is blocked on a rust feature hitting stable, so I copied in a few lines of code from that branch to support deserializing rfc3339 timestamps.
  • Loading branch information
clintfred committed Nov 19, 2021
1 parent 7363592 commit b989a0c
Show file tree
Hide file tree
Showing 10 changed files with 210 additions and 112 deletions.
18 changes: 14 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ license = "AGPL-3.0-only"
repository = "https://github.com/IronCoreLabs/ironoxide"
documentation = "https://docs.rs/ironoxide"
categories = [ "cryptography" ]
keywords = [ "cryptography", "proxy-re-encryption", "PRE", "ECC", "transform-encryption" ]
keywords = [
"cryptography",
"proxy-re-encryption",
"PRE",
"ECC",
"transform-encryption",
]
description = "A pure-Rust SDK for accessing IronCore's privacy platform"
edition = "2018"

Expand All @@ -16,7 +22,6 @@ async-trait = "0.1.21"
base64 = "0.13"
base64-serde = "0.6.1"
bytes = "1"
chrono = { version = "0.4", features = [ "serde" ] }
dashmap = "4"
futures = "0.3.1"
hex = "0.4"
Expand All @@ -34,8 +39,13 @@ recrypt = "0.12"
regex = "1.4"
reqwest = { version = "0.11", features = [ "json" ], default-features = false }
ring = { version = "0.16", features = [ "std" ] }
serde = { version = "1.0.123", features = [ "derive" ] }
serde = { version = "1.0.126", features = [ "derive" ] }
serde_json = "1"
time = { version = "0.3", features = [
"std",
"serde-human-readable",
"parsing",
] }
tokio = { version = "1", features = [ "time" ] }
url = "2.2"
vec1 = "1.6"
Expand Down Expand Up @@ -96,4 +106,4 @@ name = "ironoxide_bench"
harness = false

[package.metadata.docs.rs]
all-features = true
all-features = true
13 changes: 8 additions & 5 deletions src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use crate::internal::{
rest::{Authorization, IronCoreRequest, SignatureUrlString},
user_api::UserId,
};
use chrono::{DateTime, Utc};
use futures::Future;
use lazy_static::lazy_static;
use log::error;
Expand All @@ -27,10 +26,12 @@ use std::{
result::Result,
sync::{Mutex, MutexGuard},
};
use time::OffsetDateTime;

pub mod document_api;
pub mod group_api;
mod rest;
mod serde_rfc3339;
pub mod user_api;

lazy_static! {
Expand Down Expand Up @@ -279,6 +280,8 @@ pub fn validate_name(name: &str, name_type: &str) -> Result<String, IronOxideErr
}

pub mod auth_v2 {
use time::OffsetDateTime;

use super::*;

/// API Auth version 2.
Expand All @@ -287,11 +290,11 @@ pub mod auth_v2 {
/// Step 2 is done via `finish_with` as a request is being sent out and the bytes of the body are available.
pub struct AuthV2Builder<'a> {
pub(in crate::internal::auth_v2) req_auth: &'a RequestAuth,
pub(in crate::internal::auth_v2) timestamp: DateTime<Utc>,
pub(in crate::internal::auth_v2) timestamp: OffsetDateTime,
}

impl<'a> AuthV2Builder<'a> {
pub fn new(req_auth: &'a RequestAuth, timestamp: DateTime<Utc>) -> AuthV2Builder {
pub fn new(req_auth: &'a RequestAuth, timestamp: OffsetDateTime) -> AuthV2Builder {
AuthV2Builder {
req_auth,
timestamp,
Expand Down Expand Up @@ -335,7 +338,7 @@ pub struct RequestAuth {
impl RequestAuth {
pub fn create_signature_v2<'a>(
&'a self,
current_time: DateTime<Utc>,
current_time: OffsetDateTime,
sig_url: SignatureUrlString,
method: Method,
body: Option<&'a [u8]>,
Expand Down Expand Up @@ -1197,7 +1200,7 @@ pub(crate) mod tests {
};
let recrypt = recrypt::api::Recrypt::new();
let (_, pub_key) = recrypt.generate_key_pair()?;
let time = chrono::Utc::now();
let time = OffsetDateTime::now_utc();
let create_gmr = |id: GroupId, needs_rotation: Option<bool>| {
create_group_meta_result(
id,
Expand Down
26 changes: 13 additions & 13 deletions src/internal/document_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use crate::{
},
DeviceSigningKeyPair, PolicyCache,
};
use chrono::{DateTime, Utc};
use futures::{try_join, Future};
use hex::encode;
use itertools::{Either, Itertools};
Expand All @@ -39,6 +38,7 @@ use std::{
ops::DerefMut,
sync::Mutex,
};
use time::OffsetDateTime;

mod requests;

Expand Down Expand Up @@ -240,11 +240,11 @@ impl DocumentListMeta {
&self.0.association.typ
}
/// Date and time when the document was created
pub fn created(&self) -> &DateTime<Utc> {
pub fn created(&self) -> &OffsetDateTime {
&self.0.created
}
/// Date and time when the document was last updated
pub fn last_updated(&self) -> &DateTime<Utc> {
pub fn last_updated(&self) -> &OffsetDateTime {
&self.0.updated
}
}
Expand Down Expand Up @@ -279,11 +279,11 @@ impl DocumentMetadataResult {
self.0.name.as_ref()
}
/// Date and time when the document was created
pub fn created(&self) -> &DateTime<Utc> {
pub fn created(&self) -> &OffsetDateTime {
&self.0.created
}
/// Date and time when the document was last updated
pub fn last_updated(&self) -> &DateTime<Utc> {
pub fn last_updated(&self) -> &OffsetDateTime {
&self.0.updated
}
/// How the requesting user has access to the document
Expand Down Expand Up @@ -370,8 +370,8 @@ impl DocumentEncryptUnmanagedResult {
pub struct DocumentEncryptResult {
id: DocumentId,
name: Option<DocumentName>,
updated: DateTime<Utc>,
created: DateTime<Utc>,
updated: OffsetDateTime,
created: OffsetDateTime,
encrypted_data: Vec<u8>,
grants: Vec<UserOrGroup>,
access_errs: Vec<DocAccessEditErr>,
Expand All @@ -390,11 +390,11 @@ impl DocumentEncryptResult {
self.name.as_ref()
}
/// Date and time when the document was created
pub fn created(&self) -> &DateTime<Utc> {
pub fn created(&self) -> &OffsetDateTime {
&self.created
}
/// Date and time when the document was last updated
pub fn last_updated(&self) -> &DateTime<Utc> {
pub fn last_updated(&self) -> &OffsetDateTime {
&self.updated
}
/// Users and groups the document was successfully encrypted to
Expand All @@ -413,8 +413,8 @@ impl DocumentEncryptResult {
pub struct DocumentDecryptResult {
id: DocumentId,
name: Option<DocumentName>,
updated: DateTime<Utc>,
created: DateTime<Utc>,
updated: OffsetDateTime,
created: OffsetDateTime,
decrypted_data: Vec<u8>,
}
impl DocumentDecryptResult {
Expand All @@ -431,11 +431,11 @@ impl DocumentDecryptResult {
self.name.as_ref()
}
/// Date and time when the document was created
pub fn created(&self) -> &DateTime<Utc> {
pub fn created(&self) -> &OffsetDateTime {
&self.created
}
/// Date and time when the document was last updated
pub fn last_updated(&self) -> &DateTime<Utc> {
pub fn last_updated(&self) -> &OffsetDateTime {
&self.updated
}
}
Expand Down
42 changes: 23 additions & 19 deletions src/internal/document_api/requests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use crate::internal::{
user_api::UserId,
IronOxideErr, RequestAuth, RequestErrorCode,
};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::convert::{TryFrom, TryInto};
use time::OffsetDateTime;

#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct Association {
Expand Down Expand Up @@ -130,8 +130,10 @@ pub struct DocumentMetaApiResponse {
pub association: Association,
pub visible_to: DocumentVisibility,
pub encrypted_symmetric_key: TransformedEncryptedValue,
pub updated: DateTime<Utc>,
pub created: DateTime<Utc>,
#[serde(with = "crate::internal::serde_rfc3339")]
pub updated: OffsetDateTime,
#[serde(with = "crate::internal::serde_rfc3339")]
pub created: OffsetDateTime,
}

pub mod document_list {
Expand All @@ -147,8 +149,10 @@ pub mod document_list {
pub id: DocumentId,
pub name: Option<DocumentName>,
pub association: Association,
pub created: DateTime<Utc>,
pub updated: DateTime<Utc>,
#[serde(with = "crate::internal::serde_rfc3339")]
pub created: OffsetDateTime,
#[serde(with = "crate::internal::serde_rfc3339")]
pub updated: OffsetDateTime,
}

/// Make GET request to document list endpoint for the current user/device context
Expand All @@ -159,7 +163,7 @@ pub mod document_list {
.get(
"documents",
RequestErrorCode::DocumentList,
AuthV2Builder::new(auth, Utc::now()),
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
)
.await
}
Expand All @@ -176,7 +180,7 @@ pub mod document_get {
.get(
&format!("documents/{}", rest::url_encode(&id.0)),
RequestErrorCode::DocumentGet,
AuthV2Builder::new(auth, Utc::now()),
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
)
.await
}
Expand All @@ -194,7 +198,7 @@ pub mod edek_transform {
"edeks/transform",
edek_bytes,
RequestErrorCode::EdekTransform,
AuthV2Builder::new(auth, Utc::now()),
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
)
.await
}
Expand Down Expand Up @@ -227,14 +231,15 @@ pub mod document_create {
pub(crate) id: DocumentId,
pub(crate) value: DocumentCreateValue,
}

#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DocumentCreateResponse {
pub(crate) id: DocumentId,
pub(crate) name: Option<DocumentName>,
pub(crate) updated: DateTime<Utc>,
pub(crate) created: DateTime<Utc>,
#[serde(with = "crate::internal::serde_rfc3339")]
pub(crate) updated: OffsetDateTime,
#[serde(with = "crate::internal::serde_rfc3339")]
pub(crate) created: OffsetDateTime,
pub(crate) shared_with: Vec<AccessGrant>,
}

Expand All @@ -259,7 +264,7 @@ pub mod document_create {
"documents",
&req,
RequestErrorCode::DocumentCreate,
AuthV2Builder::new(auth, Utc::now()),
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
)
.await
}
Expand Down Expand Up @@ -310,7 +315,7 @@ pub mod policy_get {
"policies",
&query_params,
RequestErrorCode::PolicyGet,
AuthV2Builder::new(auth, Utc::now()),
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
)
.await
}
Expand All @@ -334,7 +339,7 @@ pub mod document_update {
&format!("documents/{}", rest::url_encode(&id.0)),
&DocumentUpdateRequest { name },
RequestErrorCode::DocumentUpdate,
AuthV2Builder::new(auth, Utc::now()),
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
)
.await
}
Expand Down Expand Up @@ -464,7 +469,7 @@ pub mod document_access {
&format!("documents/{}/access", rest::url_encode(id.id())),
&req,
RequestErrorCode::DocumentGrantAccess,
AuthV2Builder::new(auth, Utc::now()),
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
)
.await
}
Expand All @@ -481,15 +486,14 @@ pub mod document_access {
user_or_groups: revoke_list,
},
RequestErrorCode::DocumentRevokeAccess,
AuthV2Builder::new(auth, Utc::now()),
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
)
.await
}
}

#[cfg(test)]
mod tests {
use chrono::TimeZone;

use super::*;

Expand All @@ -498,8 +502,8 @@ mod tests {
fn document_item_serde_format_is_expected() {
use document_list::DocumentListApiResponseItem;

let created = Utc.timestamp_millis(1_551_461_529_000);
let updated = Utc.timestamp_millis(1_551_461_529_001);
let created = OffsetDateTime::from_unix_timestamp_nanos(1_551_461_529_000_000).unwrap();
let updated = OffsetDateTime::from_unix_timestamp_nanos(1_551_461_529_001_000).unwrap();
let item = DocumentListApiResponseItem {
id: DocumentId("my_id".to_string()),
name: None,
Expand Down
Loading

0 comments on commit b989a0c

Please sign in to comment.