Skip to content
Snippets Groups Projects
Verified Commit 44bde3bb authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

[NSS] Implement reverse-mapping of getent search fields

Closes #7
parent 828c1aed
No related branches found
No related tags found
No related merge requests found
......@@ -32,3 +32,6 @@ maps.passwd = """
shell: .login_shell
}
"""
# Reverse mapping to make sure uid lookups on entries mapped above still work
maps.rev.passwd.by_uid = ". - 10000"
......@@ -119,7 +119,7 @@ impl PasswdHooks for OidcPasswd {
}
};
let data: Passwd = match get_data_jq(&conf, "nss", "passwd.by_uid", uid.to_string(), &token, false).map(|PasswdHelper(p)| p) {
let data: Passwd = match get_data_jq(&conf, "nss", "passwd.by_uid", uid, &token, false).map(|PasswdHelper(p)| p) {
Ok(d) => d,
Err(e) => {
error!("Could not load JSON data for passwd: {}", e);
......
......@@ -39,7 +39,7 @@ use oauth2::reqwest::http_client;
use std::error;
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use reqwest;
use serde_json;
......@@ -151,15 +151,23 @@ fn get_data(conf: &Config, prefix: &str, endpoint: &str, param: String, token: &
.text()?)
}
fn get_jq_prog(conf: &Config, prefix: &str, endpoint: &str) -> Option<String> {
match get_optional(&conf, &full_key(vec![prefix, "maps", endpoint])) {
fn get_jq_prog(conf: &Config, prefix: &str, endpoint: &str, rev: bool) -> Option<String> {
let prog_key = match rev {
false => full_key(vec![prefix, "maps", endpoint]),
true => full_key(vec![prefix, "maps.rev", endpoint]),
};
match get_optional(&conf, &prog_key) {
Some(v) => Some (v),
None => {
if rev {
// Do not fallback to more generic program for reverse mapping
return None;
}
// Try falling back to more generic program
match endpoint.find('.') {
Some(i) => {
debug!("JQ mapping program for {} not found; trying more generic definition", endpoint);
get_jq_prog(conf, prefix, &endpoint[..i])
get_jq_prog(conf, prefix, &endpoint[..i], rev)
},
None => None
}
......@@ -167,11 +175,11 @@ fn get_jq_prog(conf: &Config, prefix: &str, endpoint: &str) -> Option<String> {
}
}
pub fn get_data_jq<T: for<'de> Deserialize<'de>>(conf: &Config, prefix: &str, endpoint: &str, param: String, token: &BasicTokenResponse, multi: bool) -> Result<T, Box<dyn error::Error>> {
let res: Option<String> = get_jq_prog(&conf, prefix, endpoint);
pub fn get_data_jq<T: for<'de> Deserialize<'de>, V: Serialize>(conf: &Config, prefix: &str, endpoint: &str, param: V, token: &BasicTokenResponse, multi: bool) -> Result<T, Box<dyn error::Error>> {
let res: Option<String> = get_jq_prog(&conf, prefix, endpoint, false);
let jq_code = match res {
Some(s) => {
debug!("Found jq mapping program for endpoint {}", endpoint);
debug!("Found jq mapping program for endpoint {}: {}", endpoint, s);
match multi {
true => "map(".to_string() + &s + ")",
false => s
......@@ -183,6 +191,30 @@ pub fn get_data_jq<T: for<'de> Deserialize<'de>>(conf: &Config, prefix: &str, en
}
};
let mut jq_prog = jq_rs::compile(&jq_code)?;
let res: Option<String> = get_jq_prog(&conf, prefix, endpoint, true);
let jq_code = match res {
Some(s) => {
debug!("Found jq reverse mapping program for endpoint {}: {}", endpoint, s);
s
},
None => {
debug!("No jq reverse mapping program for endpoint {}; using default (no-op)", endpoint);
".".to_string()
}
};
let mut jq_prog_rev = jq_rs::compile(&jq_code)?;
// Convert and transform the passed param using the reverse JQ mapping program
// 1. Serialize into JSON value (atomic) to be bale to pass into jq
let param_serialized = serde_json::to_string(&param)?;
// 2. Transform using the JQ program loaded above
let param_trans = jq_prog_rev.run(&param_serialized)?.trim().to_string();
// 3. Deserialize into serde_json value so we get numbers as numbers, strings properly unquoted
let param_deserialized: serde_json::Value = serde_json::from_str(&param_trans)?;
let param = match param_deserialized {
serde_json::Value::String(v) => v, // We want strings verbatim without JSON quoting
_ => param_deserialized.to_string() // We want numbers converted to string
};
let data_raw = get_data(&conf, prefix, endpoint, param, token)?;
let data_trans = jq_prog.run(&data_raw)?;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment