Skip to content

Commit 96d6359

Browse files
committed
Add option to verify JWT tokens in the HTTP Authorization header
1 parent 56be2d9 commit 96d6359

File tree

6 files changed

+46
-19
lines changed

6 files changed

+46
-19
lines changed

rust/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/auth-impls/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414
use api::auth::{AuthResponse, Authorizer};
1515
use api::error::VssError;
1616
use async_trait::async_trait;
17-
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
17+
use jsonwebtoken::{decode, Algorithm, Validation};
1818
use serde::{Deserialize, Serialize};
1919
use std::collections::HashMap;
2020

21+
pub use jsonwebtoken::DecodingKey;
22+
2123
/// A JWT based authorizer, only allows requests with verified 'JsonWebToken' signed by the given
2224
/// issuer key.
2325
///

rust/server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition = "2021"
55

66
[dependencies]
77
api = { path = "../api" }
8+
auth-impls = { path = "../auth-impls" }
89
impls = { path = "../impls" }
910

1011
hyper = { version = "1", default-features = false, features = ["server", "http1"] }

rust/server/src/main.rs

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@ use hyper_util::rt::TokioIo;
2020
use crate::vss_service::VssService;
2121
use api::auth::{Authorizer, NoopAuthorizer};
2222
use api::kv_store::KvStore;
23+
use auth_impls::{DecodingKey, JWTAuthorizer};
2324
use impls::postgres_store::{Certificate, PostgresPlaintextBackend, PostgresTlsBackend};
2425
use std::sync::Arc;
2526

26-
pub(crate) mod util;
27-
pub(crate) mod vss_service;
27+
mod util;
28+
mod vss_service;
29+
30+
use util::config::{Config, ServerConfig};
2831

2932
fn main() {
3033
let args: Vec<String> = std::env::args().collect();
@@ -33,22 +36,21 @@ fn main() {
3336
std::process::exit(1);
3437
}
3538

36-
let config = match util::config::load_config(&args[1]) {
37-
Ok(cfg) => cfg,
38-
Err(e) => {
39-
eprintln!("Failed to load configuration: {}", e);
40-
std::process::exit(1);
41-
},
42-
};
43-
44-
let addr: SocketAddr =
45-
match format!("{}:{}", config.server_config.host, config.server_config.port).parse() {
46-
Ok(addr) => addr,
39+
let Config { server_config: ServerConfig { host, port, rsa_pem_file }, postgresql_config } =
40+
match util::config::load_config(&args[1]) {
41+
Ok(cfg) => cfg,
4742
Err(e) => {
48-
eprintln!("Invalid host/port configuration: {}", e);
43+
eprintln!("Failed to load configuration: {}", e);
4944
std::process::exit(1);
5045
},
5146
};
47+
let addr: SocketAddr = match format!("{}:{}", host, port).parse() {
48+
Ok(addr) => addr,
49+
Err(e) => {
50+
eprintln!("Invalid host/port configuration: {}", e);
51+
std::process::exit(1);
52+
},
53+
};
5254

5355
let runtime = match tokio::runtime::Builder::new_multi_thread().enable_all().build() {
5456
Ok(runtime) => Arc::new(runtime),
@@ -66,9 +68,27 @@ fn main() {
6668
std::process::exit(-1);
6769
},
6870
};
69-
let authorizer: Arc<dyn Authorizer> = Arc::new(NoopAuthorizer {});
70-
let postgresql_config =
71-
config.postgresql_config.expect("PostgreSQLConfig must be defined in config file.");
71+
72+
let authorizer: Arc<dyn Authorizer> = if let Some(rsa_pem_file) = rsa_pem_file {
73+
let rsa_pem = match std::fs::read(rsa_pem_file) {
74+
Ok(pem) => pem,
75+
Err(e) => {
76+
println!("Failed to read RSA public key file: {}", e);
77+
std::process::exit(-1);
78+
},
79+
};
80+
let rsa_public_key = match DecodingKey::from_rsa_pem(&rsa_pem) {
81+
Ok(pem) => pem,
82+
Err(e) => {
83+
println!("Failed to parse RSA public key file: {}", e);
84+
std::process::exit(-1);
85+
},
86+
};
87+
Arc::new(JWTAuthorizer::new(rsa_public_key).await)
88+
} else {
89+
Arc::new(NoopAuthorizer {})
90+
};
91+
7292
let endpoint = postgresql_config.to_postgresql_endpoint();
7393
let db_name = postgresql_config.database;
7494
let store: Arc<dyn KvStore> = if let Some(tls_config) = postgresql_config.tls {
@@ -109,6 +129,7 @@ fn main() {
109129
Arc::new(postgres_plaintext_backend)
110130
};
111131
println!("Connected to PostgreSQL backend with DSN: {}/{}", endpoint, db_name);
132+
112133
let rest_svc_listener =
113134
TcpListener::bind(&addr).await.expect("Failed to bind listening port");
114135
println!("Listening for incoming connections on {}", addr);

rust/server/src/util/config.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ use serde::Deserialize;
33
#[derive(Deserialize)]
44
pub(crate) struct Config {
55
pub(crate) server_config: ServerConfig,
6-
pub(crate) postgresql_config: Option<PostgreSQLConfig>,
6+
pub(crate) postgresql_config: PostgreSQLConfig,
77
}
88

99
#[derive(Deserialize)]
1010
pub(crate) struct ServerConfig {
1111
pub(crate) host: String,
1212
pub(crate) port: u16,
13+
pub(crate) rsa_pem_file: Option<String>,
1314
}
1415

1516
#[derive(Deserialize)]

rust/server/vss-server-config.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[server_config]
22
host = "127.0.0.1"
33
port = 8080
4+
# rsa_pem_file = "rsa_public_key.pem" # Uncomment to verify JWT tokens in the HTTP Authorization header
45

56
[postgresql_config]
67
username = "postgres" # Optional in TOML, can be overridden by env var `VSS_POSTGRESQL_USERNAME`

0 commit comments

Comments
 (0)