-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
523 additions
and
18 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
create table carrier_keys ( | ||
pubkey text not null, | ||
entity_key text not null, | ||
created_at timestamptz not null default now(), | ||
updated_at timestamptz not null default now(), | ||
PRIMARY KEY(pubkey) | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
use crate::{key_cache::KeyCache, telemetry, verify_public_key, GrpcResult}; | ||
use chrono::Utc; | ||
use file_store::traits::{MsgVerify, TimestampEncode}; | ||
use helium_crypto::{Keypair, PublicKey, Sign}; | ||
use helium_proto::{ | ||
services::mobile_config::{self, CarrierKeyToEntityReqV1, CarrierKeyToEntityResV1}, | ||
Message, | ||
}; | ||
use sqlx::{Pool, Postgres}; | ||
use tonic::{Request, Response, Status}; | ||
|
||
pub struct CarrierService { | ||
key_cache: KeyCache, | ||
pool: Pool<Postgres>, | ||
signing_key: Keypair, | ||
} | ||
|
||
impl CarrierService { | ||
pub fn new(key_cache: KeyCache, pool: Pool<Postgres>, signing_key: Keypair) -> Self { | ||
Self { | ||
key_cache, | ||
pool, | ||
signing_key, | ||
} | ||
} | ||
|
||
fn verify_request_signature<R>(&self, signer: &PublicKey, request: &R) -> Result<(), Status> | ||
where | ||
R: MsgVerify, | ||
{ | ||
if self.key_cache.verify_signature(signer, request).is_ok() { | ||
tracing::info!(signer = signer.to_string(), "request authorized"); | ||
return Ok(()); | ||
} | ||
Err(Status::permission_denied("unauthorized request signature")) | ||
} | ||
|
||
fn sign_response(&self, response: &[u8]) -> Result<Vec<u8>, Status> { | ||
self.signing_key | ||
.sign(response) | ||
.map_err(|_| Status::internal("response signing error")) | ||
} | ||
|
||
async fn key_to_entity(&self, pubkey: &String) -> Result<String, Status> { | ||
let entity_key = sqlx::query_scalar::<_, String>( | ||
" select entity_key from carrier_keys where pubkey = $1 ", | ||
) | ||
.bind(pubkey) | ||
.fetch_one(&self.pool) | ||
.await | ||
.map_err(|_| Status::internal("carrier entity key not found"))?; | ||
Ok(entity_key) | ||
} | ||
} | ||
|
||
#[tonic::async_trait] | ||
impl mobile_config::CarrierService for CarrierService { | ||
async fn key_to_entity( | ||
&self, | ||
request: Request<CarrierKeyToEntityReqV1>, | ||
) -> GrpcResult<CarrierKeyToEntityResV1> { | ||
let request = request.into_inner(); | ||
telemetry::count_request("carrier_service", "key_to_entity"); | ||
|
||
let signer = verify_public_key(&request.signer)?; | ||
self.verify_request_signature(&signer, &request)?; | ||
|
||
let entity_key = self.key_to_entity(&request.pubkey).await?; | ||
let mut response = CarrierKeyToEntityResV1 { | ||
entity_key, | ||
timestamp: Utc::now().encode_timestamp(), | ||
signer: self.signing_key.public_key().into(), | ||
signature: vec![], | ||
}; | ||
response.signature = self.sign_response(&response.encode_to_vec())?; | ||
Ok(Response::new(response)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
use super::{call_with_retry, ClientError, Settings, CACHE_EVICTION_FREQUENCY}; | ||
use async_trait::async_trait; | ||
use file_store::traits::MsgVerify; | ||
use helium_crypto::{Keypair, PublicKey, Sign}; | ||
use helium_proto::{ | ||
services::{mobile_config, Channel}, | ||
Message, | ||
}; | ||
use retainer::Cache; | ||
use std::{sync::Arc, time::Duration}; | ||
|
||
#[async_trait] | ||
pub trait CarrierServiceVerifier { | ||
type Error; | ||
async fn key_to_rewardable_entity<'a>(&self, entity_id: &'a str) | ||
-> Result<String, Self::Error>; | ||
} | ||
#[derive(Clone)] | ||
pub struct CarrierServiceClient { | ||
client: mobile_config::CarrierServiceClient<Channel>, | ||
signing_key: Arc<Keypair>, | ||
config_pubkey: PublicKey, | ||
cache: Arc<Cache<String, String>>, | ||
cache_ttl: Duration, | ||
} | ||
|
||
#[async_trait] | ||
impl CarrierServiceVerifier for CarrierServiceClient { | ||
type Error = ClientError; | ||
|
||
async fn key_to_rewardable_entity<'a>(&self, pubkey: &'a str) -> Result<String, ClientError> { | ||
if let Some(carrier_found) = self.cache.get(&pubkey.to_string()).await { | ||
return Ok(carrier_found.value().clone()); | ||
} | ||
|
||
let mut request = mobile_config::CarrierKeyToEntityReqV1 { | ||
pubkey: pubkey.to_string(), | ||
signer: self.signing_key.public_key().into(), | ||
signature: vec![], | ||
}; | ||
request.signature = self.signing_key.sign(&request.encode_to_vec())?; | ||
tracing::debug!(?pubkey, "getting entity key for carrier on-chain"); | ||
let response = match call_with_retry!(self.client.clone().key_to_entity(request.clone())) { | ||
Ok(verify_res) => { | ||
let response = verify_res.into_inner(); | ||
response.verify(&self.config_pubkey)?; | ||
response.entity_key | ||
} | ||
Err(status) => Err(status)?, | ||
}; | ||
self.cache | ||
.insert(pubkey.to_string(), response.clone(), self.cache_ttl) | ||
.await; | ||
Ok(response) | ||
} | ||
} | ||
|
||
impl CarrierServiceClient { | ||
pub fn from_settings(settings: &Settings) -> Result<Self, Box<helium_crypto::Error>> { | ||
let cache = Arc::new(Cache::new()); | ||
let cloned_cache = cache.clone(); | ||
tokio::spawn(async move { | ||
cloned_cache | ||
.monitor(4, 0.25, CACHE_EVICTION_FREQUENCY) | ||
.await | ||
}); | ||
|
||
Ok(Self { | ||
client: settings.connect_carrier_service_client(), | ||
signing_key: settings.signing_keypair()?, | ||
config_pubkey: settings.config_pubkey()?, | ||
cache_ttl: settings.cache_ttl(), | ||
cache, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.