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_json = "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)]
extern crate biscuit;
extern crate base64;
extern crate hyper;
extern crate ldap3;
@ -8,6 +9,10 @@ extern crate tokio;
extern crate serde_derive;
use std::env;
use std::io;
use std::fs;
use std::fs::File;
use std::path::Path;
use std::str::{
FromStr,
from_utf8,
@ -20,6 +25,34 @@ use hyper::header::{AUTHORIZATION};
use hyper_router::{Route, RouterBuilder, RouterService};
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 };
#[derive(Debug)]
@ -152,30 +185,48 @@ fn auth_handler(req: Request<Body>) -> Response<Body> {
Response::new(Body::from(format!("BasicAuthentication {:?}", user)))
}
#[derive(Debug, Serialize)]
struct Key {
pub e: String,
}
#[derive(Debug, Serialize)]
struct JwksResponse {
pub keys: Vec<Key>,
fn jwk_from_pem(file_path: &Path) -> Result<JWK<Empty>, io::Error> {
let key_bytes = fs::read(file_path)?;
let rsa = Rsa::private_key_from_pem(key_bytes.as_slice()).unwrap();
Ok(JWK {
common: CommonParameters {
algorithm: Some(Algorithm::Signature(SignatureAlgorithm::RS256)),
key_id: Some(file_path.file_name().unwrap().to_str().unwrap().to_string()),
..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> {
let key = Key {
e: "what".to_string(),
};
let mut response = JwksResponse {
keys: Vec::new(),
};
response.keys.push(key);
let json_str = serde_json::to_string(&response).unwrap();
let jwks: Vec<JWK<Empty>> = fs::read_dir("./").unwrap()
.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 ext = match path.extension() {
Some(ext) => ext.to_str().unwrap().to_owned(),
None => return None,
};
match ext.as_ref() {
"pem" => Some(jwk_from_pem(path.as_path()).unwrap()),
_ => None,
}
})
.collect();
let jwks = JWKSet { keys: jwks };
let jwks_json = serde_json::to_string(&jwks).unwrap();
Response::builder()
.status(StatusCode::OK)
.header("Content-Type", "application/json")
.body(Body::from(json_str))
.body(Body::from(jwks_json))
.unwrap()
}