Skip to content

Commit

Permalink
fix: bypass rate limits
Browse files Browse the repository at this point in the history
  • Loading branch information
chris13524 committed Jun 25, 2024
1 parent 4fd6199 commit 5c63eb1
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 73 deletions.
58 changes: 28 additions & 30 deletions src/attestation_store/cf_kv.rs
Original file line number Diff line number Diff line change
@@ -1,54 +1,54 @@
use {
super::{AttestationStore, Result},
crate::http_server::{CsrfToken, TokenManager},
async_trait::async_trait,
hyper::StatusCode,
reqwest::Url,
serde::Serialize,
std::time::Duration,
};

const ATTESTATION_TTL_SECS: usize = 300;

#[derive(Clone)]
pub struct CloudflareKv {
pub account_id: String,
pub namespace_id: String,
pub bearer_token: String,
pub endpoint: Url,
pub token_manager: TokenManager,
pub http_client: reqwest::Client,
}

impl CloudflareKv {
pub fn new(account_id: String, namespace_id: String, bearer_token: String) -> Self {
pub fn new(endpoint: Url, token_manager: TokenManager) -> Self {
Self {
account_id,
namespace_id,
bearer_token,
endpoint,
token_manager,
http_client: reqwest::Client::new(),
}
}
}

#[derive(Serialize)]
struct SetBulkBody<'a> {
expiration_ttl: usize,
key: &'a str,
value: &'a str,
#[serde(rename_all = "camelCase")]
struct SetAttestationCompatBody<'a> {
attestation_id: &'a str,
origin: &'a str,
}

#[async_trait]
impl AttestationStore for CloudflareKv {
async fn set_attestation(&self, id: &str, origin: &str) -> Result<()> {
let url = format!(
"https://api.cloudflare.com/client/v4/accounts/{account_id}/storage/kv/namespaces/{namespace_id}/bulk",
account_id = self.account_id, namespace_id = self.namespace_id
);
let url = self.endpoint.join("/attestation")?;
let res = self
.http_client
.put(&url)
.bearer_auth(&self.bearer_token)
.json(&vec![SetBulkBody {
expiration_ttl: ATTESTATION_TTL_SECS,
key: id,
value: origin,
}])
.post(url)
.header(
CsrfToken::header_name(),
self.token_manager
.generate_csrf_token()
.map_err(|e| anyhow::anyhow!("{e:?}"))?,
)
.json(&SetAttestationCompatBody {
attestation_id: id,
origin,
})
.timeout(Duration::from_secs(1))
.send()
.await?;
Expand All @@ -64,14 +64,12 @@ impl AttestationStore for CloudflareKv {
}

async fn get_attestation(&self, id: &str) -> Result<Option<String>> {
let url = format!(
"https://api.cloudflare.com/client/v4/accounts/{account_id}/storage/kv/namespaces/{namespace_id}/values/{id}",
account_id = self.account_id, namespace_id = self.namespace_id
);
let url = self
.endpoint
.join(&format!("/v1/compat-attestation/{id}"))?;
let response = self
.http_client
.get(&url)
.bearer_auth(&self.bearer_token)
.get(url)
.timeout(Duration::from_secs(1))
.send()
.await?;
Expand Down
11 changes: 6 additions & 5 deletions src/http_server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,14 @@ impl<S, G> Server<S, G> {
}
}

struct TokenManager {
#[derive(Clone)]
pub struct TokenManager {
encoding_key: jsonwebtoken::EncodingKey,
decoding_key: jsonwebtoken::DecodingKey,
}

impl TokenManager {
fn new(secret: &[u8]) -> Self {
pub fn new(secret: &[u8]) -> Self {
Self {
encoding_key: jsonwebtoken::EncodingKey::from_secret(secret),
decoding_key: jsonwebtoken::DecodingKey::from_secret(secret),
Expand Down Expand Up @@ -262,14 +263,14 @@ where
}

#[derive(Serialize, Deserialize)]
struct CsrfToken {
pub struct CsrfToken {
exp: usize,
}

impl CsrfToken {
// Using const value instead of a fn produces this warning:
// https://rust-lang.github.io/rust-clippy/master/index.html#declare_interior_mutable_const
const fn header_name() -> HeaderName {
pub const fn header_name() -> HeaderName {
HeaderName::from_static("x-csrf-token")
}

Expand All @@ -282,7 +283,7 @@ impl CsrfToken {
}

impl TokenManager {
fn generate_csrf_token(&self) -> Result<String, Response> {
pub fn generate_csrf_token(&self) -> Result<String, Response> {
use jsonwebtoken::{encode, get_current_timestamp, Header};

const TTL_SECS: usize = 60 * 60; // 1 hour
Expand Down
14 changes: 7 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use {
bouncer::{
attestation_store::{cf_kv::CloudflareKv, migration::MigrationStore},
event_sink,
http_server::{RequestInfo, ServerConfig},
http_server::{RequestInfo, ServerConfig, TokenManager},
project_registry::{self, CachedExt as _},
scam_guard,
util::redis,
Expand Down Expand Up @@ -56,9 +56,7 @@ pub struct Configuration {
pub data_api_auth_token: String,
pub scam_guard_cache_url: String,

pub cf_kv_account_id: String,
pub cf_kv_namespace_id: String,
pub cf_kv_bearer_token: String,
pub cf_kv_endpoint: String,

pub secret: String,

Expand Down Expand Up @@ -109,9 +107,11 @@ async fn main() -> Result<(), anyhow::Error> {
redis::new("attestation_store", config.attestation_cache_url.clone())
.context("Failed to initialize AttestationStore")?;
let cf_kv_attestation_store = CloudflareKv::new(
config.cf_kv_account_id,
config.cf_kv_namespace_id,
config.cf_kv_bearer_token,
config
.cf_kv_endpoint
.parse()
.context("Failed to parse cf_kv_endpoint")?,
TokenManager::new(config.secret.as_bytes()),
);
MigrationStore::new(redis_attestation_store, cf_kv_attestation_store)
};
Expand Down
4 changes: 1 addition & 3 deletions terraform/ecs/cluster.tf
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,7 @@ resource "aws_ecs_task_definition" "app_task" {
{ name = "PROJECT_REGISTRY_CACHE_URL", value = var.project_registry_cache_url },
{ name = "SCAM_GUARD_CACHE_URL", value = var.scam_guard_cache_url },

{ name = "CF_KV_ACCOUNT_ID", value = var.cf_kv_account_id },
{ name = "CF_KV_NAMESPACE_ID", value = var.cf_kv_namespace_id },
{ name = "CF_KV_BEARER_TOKEN", value = var.cf_kv_bearer_token },
{ name = "CF_KV_ENDPOINT", value = var.cf_kv_endpoint },

{ name = "DATA_LAKE_BUCKET", value = var.analytics_datalake_bucket_name },

Expand Down
14 changes: 2 additions & 12 deletions terraform/ecs/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -152,18 +152,8 @@ variable "scam_guard_cache_url" {
type = string
}

variable "cf_kv_account_id" {
description = "The account ID of the Cloudflare KV store"
type = string
}

variable "cf_kv_namespace_id" {
description = "The namespace ID of the Cloudflare KV store"
type = string
}

variable "cf_kv_bearer_token" {
description = "The Cloudflare API bearer token"
variable "cf_kv_endpoint" {
description = "The endpoint of the Cloudflare KV worker"
type = string
}

Expand Down
4 changes: 1 addition & 3 deletions terraform/res_ecs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ module "ecs" {
project_registry_cache_url = "redis://${module.redis.endpoint}/1"
scam_guard_cache_url = "redis://${module.redis.endpoint}/2"

cf_kv_account_id = var.cf_kv_account_id
cf_kv_namespace_id = var.cf_kv_namespace_id
cf_kv_bearer_token = var.cf_kv_bearer_token
cf_kv_endpoint = var.cf_kv_endpoint

ofac_blocked_countries = var.ofac_blocked_countries

Expand Down
15 changes: 2 additions & 13 deletions terraform/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -78,22 +78,11 @@ variable "ofac_blocked_countries" {
#-------------------------------------------------------------------------------
# Cloudflare KV for V2 migration

variable "cf_kv_account_id" {
description = "The account ID of the Cloudflare KV store"
variable "cf_kv_endpoint" {
description = "The endpoint of the Cloudflare KV worker"
type = string
}

variable "cf_kv_namespace_id" {
description = "The namespace ID of the Cloudflare KV store"
type = string
}

variable "cf_kv_bearer_token" {
description = "The Cloudflare API bearer token"
type = string
}


#-------------------------------------------------------------------------------
# Project Registry

Expand Down

0 comments on commit 5c63eb1

Please sign in to comment.