Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DEVEX-2333]: Implement caching using dynamo #183

Merged
merged 27 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ jobs:
- run: cargo make deny-check
- run: cargo make docs
test:
services:
aws:
image: public.ecr.aws/localstack/localstack:4
ports:
- "4566:4566"
env:
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_ENDPOINT_URL: http://localhost:4566
AWS_REGION: eu-west-1
# Avoid duplicate jobs on PR from a branch on the same repo
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions .rustfmt.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
edition = "2021"
reorder_imports = true
reorder_modules = true
max_width = 120
Expand Down
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,22 @@ and this project adheres to

---

## [0.21.0] - 2025-02-10

# Fixed

- Fixed docs.rs not building the documentation

# Deprecated

- Deprecated a lot of old auth0 APIs. See the docs for alternatives to use.

# Added

- DynamoDB cache provider

---

## [0.20.0] - 2024-12-02

### Added
Expand Down Expand Up @@ -496,7 +512,9 @@ Request::rest(&bridge).send()

The old API is still available but deprecated. It will be removed soon.

[Unreleased]: https://github.com/primait/bridge.rs/compare/0.20.0...HEAD

[Unreleased]: https://github.com/primait/bridge.rs/compare/0.21.0...HEAD
[0.21.0]: https://github.com/primait/bridge.rs/compare/0.20.0...0.21.0
[0.20.0]: https://github.com/primait/bridge.rs/compare/0.19.0...0.20.0
[0.19.0]: https://github.com/primait/bridge.rs/compare/0.18.0...0.19.0
[0.18.0]: https://github.com/primait/bridge.rs/compare/0.17.0...0.18.0
Expand Down
23 changes: 18 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ license = "MIT"
name = "prima_bridge"
readme = "README.md"
repository = "https://github.com/primait/bridge.rs"
version = "0.20.0"
version = "0.21.0"
# See https://github.com/rust-lang/rust/issues/107557
rust-version = "1.72"
rust-version = "1.81"

[features]
default = ["tracing_opentelemetry"]

# Feature set that should be used
# This exists to avoid compatibility issues with otel version conflicts
_docs = ["auth0", "cache-dynamodb", "grpc", "gzip", "redis-tls", "tracing_opentelemetry"]

auth0 = [
"rand",
"redis",
Expand All @@ -22,9 +26,12 @@ auth0 = [
"dashmap",
"tracing",
]
grpc = ["tonic"]
grpc = [ "_any_otel_version", "tonic"]
gzip = ["reqwest/gzip"]
redis-tls = ["redis/tls", "redis/tokio-native-tls-comp"]

redis-tls = [ "redis", "redis/tls", "redis/tokio-native-tls-comp"]
cache-dynamodb = [ "aws-sdk-dynamodb" ]
MaeIsBad marked this conversation as resolved.
Show resolved Hide resolved

tracing_opentelemetry = ["tracing_opentelemetry_0_27"]

tracing_opentelemetry_0_21 = [
Expand Down Expand Up @@ -102,6 +109,7 @@ tonic = { version = "0.12", default-features = false, optional = true }
tracing = { version = "0.1", optional = true }
uuid = { version = ">=0.7.0, <2.0.0", features = ["serde", "v4"] }
chacha20poly1305 = { version = "0.10.1", features = ["std"], optional = true }
aws-sdk-dynamodb = { version = "1.63", optional = true }
MaeIsBad marked this conversation as resolved.
Show resolved Hide resolved

reqwest-middleware = { version = "0.4.0", features = ["json", "multipart"] }
http = "1.0.0"
Expand Down Expand Up @@ -129,6 +137,7 @@ tracing-opentelemetry_0_27_pkg = { package = "tracing-opentelemetry", version =
tracing-opentelemetry_0_28_pkg = { package = "tracing-opentelemetry", version = "0.28", optional = true }

[dev-dependencies]
aws-config = { version = "1.5.16", features = ["behavior-version-latest"] }
flate2 = "1.0"
mockito = "1.0"
tokio = { version = "1.16", features = ["macros", "rt-multi-thread"] }
Expand All @@ -139,7 +148,11 @@ codegen-units = 1
lto = "thin"

[package.metadata.docs.rs]
all-features = true
all-features = false
# Avoid opentelemetry version conflicts
features = [
"_docs"
]
rustdoc-args = ["--cfg", "docsrs"]

[[example]]
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM rust:1.72
FROM rust:1.81

WORKDIR /code

Expand Down
4 changes: 2 additions & 2 deletions Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ dependencies = ["build"]

[tasks.test-auth0]
command = "cargo"
args = ["test", "--features=auth0,gzip", "${@}"]
args = ["test", "--features=auth0,gzip,cache-dynamodb", "${@}"]
dependencies = ["build"]

[tasks.test-all-otel-versions]
Expand Down Expand Up @@ -80,7 +80,7 @@ dependencies = ["build"]
command = "cargo"
args = [
"clippy",
"--features=auth0,gzip",
"--features=auth0,cache-dynamodb,gzip",
"--all-targets",
"--",
"-D",
Expand Down
10 changes: 10 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ services:
CARGO_HOME: /home/app/.cargo
CARGO_TARGET_DIR: /home/app/target
CARGO_MAKE_DISABLE_UPDATE_CHECK: 1
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_ENDPOINT_URL: http://aws:4566
AWS_REGION: eu-west-1
volumes:
- ".:/code"
- "app:/home/app/"
Expand All @@ -17,6 +21,12 @@ services:
- "~/.gitignore:/home/app/.gitignore"
tty: true
stdin_open: true
depends_on:
- aws
aws:
image: public.ecr.aws/localstack/localstack:4
ports:
- "4566:4566"

volumes:
app:
36 changes: 18 additions & 18 deletions examples/auth0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const QUERY: &str = "query($input:JobsInput!){jobs(input:$input) {\nid\n title\n
#[tokio::main]
async fn main() {
let bridge: Bridge = Bridge::builder()
.with_auth0(auth0::config())
.with_refreshing_token(auth0::refreshing_token().await)
.await
.build(URL.parse().unwrap());

Expand Down Expand Up @@ -113,30 +113,30 @@ pub struct Job {
mod auth0 {
use std::time::Duration;

use prima_bridge::auth0::{CacheType, Config, StalenessCheckPercentage};

pub fn config() -> Config {
use reqwest::Url;
use std::str::FromStr;
use prima_bridge::auth0::{cache::InMemoryCache, Auth0Client, RefreshingToken, StalenessCheckPercentage};

pub async fn refreshing_token() -> RefreshingToken {
let token_url: String = std::env::var("TOKEN_URL").unwrap();
let jwks_url: String = std::env::var("JWKS_URL").unwrap();
let client_id: String = std::env::var("CLIENT_ID").unwrap();
let client_secret: String = std::env::var("CLIENT_SECRET").unwrap();
let audience: String = std::env::var("AUDIENCE").unwrap();

Config {
token_url: Url::from_str(token_url.as_str()).unwrap(),
jwks_url: Url::from_str(jwks_url.as_str()).unwrap(),
caller: "paperboy".to_string(),
audience,
cache_type: CacheType::Inmemory,
token_encryption_key: "32char_long_token_encryption_key".to_string(),
check_interval: Duration::from_secs(2),
staleness_check_percentage: StalenessCheckPercentage::new(0.1, 0.5),
let auth0_client = Auth0Client::new(
token_url.parse().unwrap(),
reqwest::Client::default(),
client_id,
client_secret,
scope: Some("profile email".to_string()),
}
);

RefreshingToken::new(
auth0_client,
Duration::from_secs(10),
StalenessCheckPercentage::default(),
Box::new(InMemoryCache::default()),
audience,
None,
)
.await
.unwrap()
}
}
16 changes: 11 additions & 5 deletions src/auth0/cache/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ use chacha20poly1305::{aead::Aead, AeadCore, KeyInit, XChaCha20Poly1305};
use rand::thread_rng;
use serde::{Deserialize, Serialize};

use crate::auth0::errors::Auth0Error;

const NONCE_SIZE: usize = 24;

pub fn encrypt<T: Serialize>(value_ref: &T, token_encryption_key_str: &str) -> Result<Vec<u8>, Auth0Error> {
#[derive(thiserror::Error, Debug)]
pub enum CryptoError {
#[error(transparent)]
Serde(#[from] serde_json::Error),
#[error(transparent)]
ChaCha20Poly1305(#[from] chacha20poly1305::Error),
}

pub fn encrypt<T: Serialize>(value_ref: &T, token_encryption_key_str: &str) -> Result<Vec<u8>, CryptoError> {
let json: String = serde_json::to_string(value_ref)?;

let enc = XChaCha20Poly1305::new_from_slice(token_encryption_key_str.as_bytes()).unwrap();
Expand All @@ -18,7 +24,7 @@ pub fn encrypt<T: Serialize>(value_ref: &T, token_encryption_key_str: &str) -> R
Ok(ciphertext)
}

pub fn decrypt<T>(token_encryption_key_str: &str, encrypted: &[u8]) -> Result<T, Auth0Error>
pub fn decrypt<T>(token_encryption_key_str: &str, encrypted: &[u8]) -> Result<T, CryptoError>
where
for<'de> T: Deserialize<'de>,
{
Expand All @@ -28,7 +34,7 @@ where
let nonce = encrypted.get(encrypted.len() - NONCE_SIZE..);

let (Some(ciphertext), Some(nonce)) = (ciphertext, nonce) else {
return Err(Auth0Error::CryptoError(chacha20poly1305::Error));
return Err(CryptoError::ChaCha20Poly1305(chacha20poly1305::Error));
};

let nonce = chacha20poly1305::XNonce::from_slice(nonce);
Expand Down
Loading