-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add constructor to make KeyCache without settings file * Add test for who is authorized to request gateway info I'm not sure where the mobile_hotspot_infos table exists, but I think this test does well enough keying off expected grpc error statuses. * Add verify method that allows gateway to request info about self * use KeyTag::default in KeyPair generation for tests * tighten gw info perm check to require proto request The method before was named specifically for the info request, but the function signature was much looser than the name implied. Passing the request reduces the chance of messing up argument order, or misunderstanding the arguments. If at some point more methods require the ability for self authorization, hopefully a better abstraction will reveal itself.
- Loading branch information
1 parent
cb684d2
commit fe059f9
Showing
8 changed files
with
124 additions
and
23 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
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,93 @@ | ||
use helium_crypto::{KeyTag, Keypair, PublicKey, Sign}; | ||
use helium_proto::services::mobile_config::{self as proto, GatewayClient}; | ||
use mobile_config::{ | ||
gateway_service::GatewayService, | ||
key_cache::{CacheKeys, KeyCache}, | ||
KeyRole, | ||
}; | ||
use prost::Message; | ||
use sqlx::PgPool; | ||
use tokio::net::TcpListener; | ||
use tonic::{transport, Code}; | ||
|
||
#[sqlx::test] | ||
async fn gateway_info_authorization_errors(pool: PgPool) -> anyhow::Result<()> { | ||
// NOTE(mj): The information we're requesting does not exist in the DB for | ||
// this test. But we're only interested in Authization Errors. | ||
|
||
let admin_key = make_keypair(); // unlimited access | ||
let gw_key = make_keypair(); // access to self | ||
let unknown_key = make_keypair(); // no access | ||
let server_key = make_keypair(); // signs responses | ||
|
||
// Let the OS assign a port | ||
let listener = TcpListener::bind("127.0.0.1:0").await?; | ||
let addr = listener.local_addr()?; | ||
|
||
// Start the gateway server | ||
let keys = CacheKeys::from_iter([(admin_key.public_key().to_owned(), KeyRole::Administrator)]); | ||
let (_key_cache_tx, key_cache) = KeyCache::new(keys); | ||
let gws = GatewayService::new(key_cache, pool.clone(), server_key); | ||
let _handle = tokio::spawn( | ||
transport::Server::builder() | ||
.add_service(proto::GatewayServer::new(gws)) | ||
.serve_with_incoming(tokio_stream::wrappers::TcpListenerStream::new(listener)), | ||
); | ||
|
||
// Connect with the assigned address | ||
let mut client = GatewayClient::connect(format!("http://{addr}")).await?; | ||
|
||
// Request information about ourselves | ||
let req = make_signed_info_request(gw_key.public_key(), &gw_key); | ||
let err = client.info(req).await.expect_err("testing expects error"); | ||
assert_ne!( | ||
err.code(), | ||
Code::PermissionDenied, | ||
"gateway can request infomation about itself" | ||
); | ||
|
||
// Request gateway info as administrator | ||
let req = make_signed_info_request(gw_key.public_key(), &admin_key); | ||
let err = client.info(req).await.expect_err("testing expects error"); | ||
assert_ne!( | ||
err.code(), | ||
Code::PermissionDenied, | ||
"admins have full access" | ||
); | ||
|
||
// Request gateway from unknown key | ||
let req = make_signed_info_request(gw_key.public_key(), &unknown_key); | ||
let err = client.info(req).await.expect_err("testing expects errors"); | ||
assert_eq!( | ||
err.code(), | ||
Code::PermissionDenied, | ||
"unknown keys are denied" | ||
); | ||
|
||
// Request self with a different signer | ||
let mut req = make_signed_info_request(gw_key.public_key(), &gw_key); | ||
req.signature = vec![]; | ||
req.signature = admin_key.sign(&req.encode_to_vec()).unwrap(); | ||
let err = client.info(req).await.expect_err("testing expects errors"); | ||
assert_eq!( | ||
err.code(), | ||
Code::PermissionDenied, | ||
"signature must match signer" | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
fn make_keypair() -> Keypair { | ||
Keypair::generate(KeyTag::default(), &mut rand::rngs::OsRng) | ||
} | ||
|
||
fn make_signed_info_request(address: &PublicKey, signer: &Keypair) -> proto::GatewayInfoReqV1 { | ||
let mut req = proto::GatewayInfoReqV1 { | ||
address: address.to_vec(), | ||
signer: signer.public_key().to_vec(), | ||
signature: vec![], | ||
}; | ||
req.signature = signer.sign(&req.encode_to_vec()).unwrap(); | ||
req | ||
} |