Use biscuit's JWK structures to format /get_keys.

New method to load a .pem and a loop over current dir for any .pem
This commit is contained in:
Alex Wright 2020-02-23 19:42:32 +01:00
parent 467a449457
commit e6f9148865
2 changed files with 73 additions and 18 deletions

View File

@ -14,3 +14,7 @@ base64 = "0.10.0"
serde = "1.0.40" serde = "1.0.40"
serde_json = "1.0.40" serde_json = "1.0.40"
serde_derive = "1.0.40" serde_derive = "1.0.40"
biscuit = "0.3.1"
ring = "0.16.5"
num = "0.2"
openssl = "0.10.28"

View File

@ -1,4 +1,5 @@
#![deny(warnings)] #![deny(warnings)]
extern crate biscuit;
extern crate base64; extern crate base64;
extern crate hyper; extern crate hyper;
extern crate ldap3; extern crate ldap3;
@ -8,6 +9,10 @@ extern crate tokio;
extern crate serde_derive; extern crate serde_derive;
use std::env; use std::env;
use std::io;
use std::fs;
use std::fs::File;
use std::path::Path;
use std::str::{ use std::str::{
FromStr, FromStr,
from_utf8, from_utf8,
@ -20,6 +25,34 @@ use hyper::header::{AUTHORIZATION};
use hyper_router::{Route, RouterBuilder, RouterService}; use hyper_router::{Route, RouterBuilder, RouterService};
use base64::decode; use base64::decode;
use ring::signature::RsaKeyPair;
use biscuit::{
ClaimsSet,
Empty,
JWT,
RegisteredClaims,
SingleOrMultiple,
};
use biscuit::jwa::{
SignatureAlgorithm,
Algorithm,
};
use biscuit::jwk::{
RSAKeyParameters,
CommonParameters,
AlgorithmParameters,
JWK,
JWKSet,
};
use biscuit::jws::{
Secret,
RegisteredHeader,
};
use num::BigUint;
use openssl::bn::BigNum;
use openssl::rsa::Rsa;
use openssl::rsa::RsaPrivateKeyBuilder;
use ldap3::{ LdapConn, Scope, SearchEntry }; use ldap3::{ LdapConn, Scope, SearchEntry };
#[derive(Debug)] #[derive(Debug)]
@ -152,30 +185,48 @@ fn auth_handler(req: Request<Body>) -> Response<Body> {
Response::new(Body::from(format!("BasicAuthentication {:?}", user))) Response::new(Body::from(format!("BasicAuthentication {:?}", user)))
} }
#[derive(Debug, Serialize)] fn jwk_from_pem(file_path: &Path) -> Result<JWK<Empty>, io::Error> {
struct Key { let key_bytes = fs::read(file_path)?;
pub e: String, let rsa = Rsa::private_key_from_pem(key_bytes.as_slice()).unwrap();
} Ok(JWK {
common: CommonParameters {
#[derive(Debug, Serialize)] algorithm: Some(Algorithm::Signature(SignatureAlgorithm::RS256)),
struct JwksResponse { key_id: Some(file_path.file_name().unwrap().to_str().unwrap().to_string()),
pub keys: Vec<Key>, ..Default::default()
},
algorithm: AlgorithmParameters::RSA(RSAKeyParameters {
n: BigUint::from_bytes_be(&rsa.n().to_vec()),
e: BigUint::from_bytes_be(&rsa.e().to_vec()),
..Default::default()
}),
additional: Default::default(),
})
} }
fn get_keys(_req: Request<Body>) -> Response<Body> { fn get_keys(_req: Request<Body>) -> Response<Body> {
let key = Key { let jwks: Vec<JWK<Empty>> = fs::read_dir("./").unwrap()
e: "what".to_string(), .filter_map(|dir_entry| {
let path = dir_entry.unwrap().path();
let filename = match path.file_name() {
Some(filename) => filename.to_str().unwrap().to_owned(),
None => return None,
}; };
let mut response = JwksResponse { let ext = match path.extension() {
keys: Vec::new(), Some(ext) => ext.to_str().unwrap().to_owned(),
None => return None,
}; };
response.keys.push(key); match ext.as_ref() {
"pem" => Some(jwk_from_pem(path.as_path()).unwrap()),
let json_str = serde_json::to_string(&response).unwrap(); _ => None,
}
})
.collect();
let jwks = JWKSet { keys: jwks };
let jwks_json = serde_json::to_string(&jwks).unwrap();
Response::builder() Response::builder()
.status(StatusCode::OK) .status(StatusCode::OK)
.header("Content-Type", "application/json") .header("Content-Type", "application/json")
.body(Body::from(json_str)) .body(Body::from(jwks_json))
.unwrap() .unwrap()
} }