fix paths handling in hagrid (for nginx, too)

This commit is contained in:
Vincent Breitmoser 2019-04-28 22:41:41 +02:00
parent 848f03e95c
commit 34bce1ee22
6 changed files with 84 additions and 64 deletions

4
.gitignore vendored
View File

@ -1,8 +1,6 @@
/Rocket.toml
/target
/state
**/*.rs.bk
/dist/public/by-*
/dist/verification_tokens/*
/dist/deletion_tokens/*
**/.*.swp
**/.*.swo

View File

@ -1,11 +1,6 @@
[global]
address = "0.0.0.0"
port = 8080
template_dir = "dist/templates"
assets_dir = "dist/assets"
keys_dir = "dist/keys"
token_dir = "dist/tokens"
tmp_dir = "dist/tmp"
[development]
base-URI = "http://localhost:8080"
@ -13,13 +8,35 @@ from = "noreply@localhost"
x-accel-redirect = false
token_secret = "hagrid"
token_validity = 3600
template_dir = "dist/templates"
assets_dir = "dist/assets"
keys_internal_dir = "state/keys-internal"
keys_external_dir = "state/keys-external"
token_dir = "state/tokens"
tmp_dir = "state/tmp"
[staging]
base-URI = "https://keys.openpgp.org"
from = "noreply@keys.openpgp.org"
x-accel-redirect = true
token_secret = "hagrid"
token_validity = 3600
template_dir = "templates"
keys_internal_dir = "keys"
keys_external_dir = "public/keys"
assets_dir = "public/assets"
token_dir = "tokens"
tmp_dir = "tmp"
[production]
base-URI = "https://keys.openpgp.org"
from = "noreply@keys.openpgp.org"
x-accel-redirect = true
token_secret = "generated production secret"
token_validity = 3600
template_dir = "templates"
keys_internal_dir = "keys"
keys_external_dir = "public/keys"
assets_dir = "public/assets"
token_dir = "tokens"
tmp_dir = "tmp"

View File

@ -24,7 +24,8 @@ pub struct Filesystem {
tmp_dir: PathBuf,
keys_dir: PathBuf,
keys_internal_dir: PathBuf,
keys_external_dir: PathBuf,
keys_dir_full: PathBuf,
keys_dir_published: PathBuf,
@ -51,11 +52,12 @@ impl Filesystem {
let keys_dir = base_dir.join("keys");
let tmp_dir = base_dir.join("tmp");
Self::new(keys_dir, tmp_dir)
Self::new(&keys_dir, &keys_dir, tmp_dir)
}
pub fn new(
keys_dir: impl Into<PathBuf>,
keys_internal_dir: impl Into<PathBuf>,
keys_external_dir: impl Into<PathBuf>,
tmp_dir: impl Into<PathBuf>,
) -> Result<Self> {
@ -90,25 +92,28 @@ impl Filesystem {
let tmp_dir = tmp_dir.into();
create_dir_all(&tmp_dir)?;
let keys_dir: PathBuf = keys_dir.into();
let keys_dir_full = keys_dir.join("full");
let keys_dir_published = keys_dir.join("published");
let keys_internal_dir: PathBuf = keys_internal_dir.into();
let keys_external_dir: PathBuf = keys_external_dir.into();
let keys_dir_full = keys_internal_dir.join("full");
let keys_dir_published = keys_external_dir.join("published");
create_dir_all(&keys_dir_full)?;
create_dir_all(&keys_dir_published)?;
let links_dir_by_keyid = keys_dir.join("by-keyid");
let links_dir_by_fingerprint = keys_dir.join("by-fpr");
let links_dir_by_email = keys_dir.join("by-email");
let links_dir_by_keyid = keys_external_dir.join("by-keyid");
let links_dir_by_fingerprint = keys_external_dir.join("by-fpr");
let links_dir_by_email = keys_external_dir.join("by-email");
create_dir_all(&links_dir_by_keyid)?;
create_dir_all(&links_dir_by_fingerprint)?;
create_dir_all(&links_dir_by_email)?;
info!("Opened filesystem database.");
info!("keys_dir: '{}'", keys_dir.display());
info!("keys_internal_dir: '{}'", keys_internal_dir.display());
info!("keys_external_dir: '{}'", keys_external_dir.display());
info!("tmp_dir: '{}'", tmp_dir.display());
Ok(Filesystem {
update_lock: FlockMutex::new(&keys_dir)?,
keys_dir,
update_lock: FlockMutex::new(&keys_internal_dir)?,
keys_internal_dir,
keys_external_dir,
tmp_dir,
keys_dir_full,
@ -152,11 +157,12 @@ impl Filesystem {
self.links_dir_by_email.join(path_split(&email))
}
fn read_from_path(&self, path: &Path) -> Option<String> {
fn read_from_path(&self, path: &Path, allow_internal: bool) -> Option<String> {
use std::fs;
if !path.starts_with(&self.keys_dir) {
panic!("Attempted to access file outside keys_dir!");
if !path.starts_with(&self.keys_external_dir) &&
!(allow_internal && path.starts_with(&self.keys_internal_dir)) {
panic!("Attempted to access file outside expected dirs!");
}
if path.exists() {
@ -441,7 +447,7 @@ impl Database for Filesystem {
};
if path.exists() {
let x = diff_paths(&path, &self.keys_dir).expect("related paths");
let x = diff_paths(&path, &self.keys_external_dir).expect("related paths");
Some(x)
} else {
None
@ -516,25 +522,25 @@ impl Database for Filesystem {
// XXX: slow
fn by_fpr_full(&self, fpr: &Fingerprint) -> Option<String> {
let path = self.fingerprint_to_path_full(fpr);
self.read_from_path(&path)
self.read_from_path(&path, true)
}
// XXX: slow
fn by_fpr(&self, fpr: &Fingerprint) -> Option<String> {
let path = self.link_by_fingerprint(fpr);
self.read_from_path(&path)
self.read_from_path(&path, false)
}
// XXX: slow
fn by_email(&self, email: &Email) -> Option<String> {
let path = self.link_by_email(&email);
self.read_from_path(&path)
self.read_from_path(&path, false)
}
// XXX: slow
fn by_kid(&self, kid: &KeyID) -> Option<String> {
let path = self.link_by_keyid(kid);
self.read_from_path(&path)
self.read_from_path(&path, false)
}
}

View File

@ -2,7 +2,7 @@
{{#if uid_status}}
<p>
Your key <span class="fingerprint"><a href="{{key_link}}">{{key_fpr}}</a></span> is published for the following addresses.
Your key <span class="fingerprint"><a href="{{key_link}}" target="_blank">{{key_fpr}}</a></span> is published for the following addresses.
</p>
{{#each uid_status}}

View File

@ -5,24 +5,24 @@
client_max_body_size 1m;
location /vks/v1/by-email/ {
rewrite "^/vks/v1/by-email/([^/]{2})([^/]*)$" /by-email/$1/$2 break;
rewrite "^/vks/v1/by-email/([^/][^/])([^/][^/])([^/]*)$" /by-email/$1$2$3 break;
default_type application/pgp-keys;
add_header Content-Disposition 'attachment; filename="$1$2.asc"';
try_files /$uri =404;
add_header Content-Disposition 'attachment; filename="$1$2$3.asc"';
try_files /by-email/$1/$2/$3 @fallback;
}
location /vks/v1/by-fingerprint/ {
rewrite ^/vks/v1/by-fingerprint/(0x)?([^/][^/])(..*)$ /vks/v1/by-fingerprint/$2$3 break;
rewrite ^/vks/v1/by-fingerprint/(0x)?([^/][^/])([^/][^/])(..*)$ /vks/v1/by-fingerprint/$2$3$4 break;
default_type application/pgp-keys;
add_header Content-Disposition 'attachment; filename="$2$3.asc"';
try_files /by-fpr/$2/$3 @fallback;
add_header Content-Disposition 'attachment; filename="$2$3$4.asc"';
try_files /by-fpr/$2/$3/$4 @fallback;
}
location /vks/v1/by-keyid/ {
rewrite ^/vks/v1/by-keyid/(0x)?([^/][^/])(.*)$ /vks/v1/by-keyid/$2$3 break;
rewrite ^/vks/v1/by-keyid/(0x)?([^/][^/])([^/][^/])(.*)$ /vks/v1/by-keyid/$2$3$4 break;
default_type application/pgp-keys;
add_header Content-Disposition 'attachment; filename="$2$3.asc"';
try_files /by-keyid/$2/$3 @fallback;
add_header Content-Disposition 'attachment; filename="$2$3$4.asc"';
try_files /by-keyid/$2/$3/$4 @fallback;
}
# Pass queries that we do not understand to hagrid.
@ -57,22 +57,7 @@ location /pks/lookup {
proxy_pass http://127.0.0.1:8080;
}
location /pks/add {
proxy_pass http://127.0.0.1:8080;
}
location = / {
proxy_cache static_cache;
proxy_pass http://127.0.0.1:8080;
}
location = /about {
proxy_cache static_cache;
proxy_pass http://127.0.0.1:8080;
}
location = /apidoc {
proxy_cache static_cache;
location /pks {
proxy_pass http://127.0.0.1:8080;
}
@ -80,10 +65,22 @@ location /vks/v1/ {
proxy_pass http://127.0.0.1:8080;
}
location = /delete {
location /manage {
proxy_pass http://127.0.0.1:8080;
}
location = /publish {
location /publish {
proxy_pass http://127.0.0.1:8080;
}
# explicitly cache the home directory
location = / {
proxy_cache static_cache;
proxy_pass http://127.0.0.1:8080;
}
# cache "about" pages
location /about {
proxy_cache static_cache;
proxy_pass http://127.0.0.1:8080;
}

View File

@ -169,7 +169,7 @@ pub struct HagridState {
assets_dir: PathBuf,
/// The keys directory, where keys are located, served by hagrid or nginx
keys_dir: PathBuf,
keys_external_dir: PathBuf,
/// XXX
base_uri: String,
@ -193,7 +193,7 @@ fn key_to_response<'a>(state: rocket::State<HagridState>,
if machine_readable {
if state.x_accel_redirect {
if let Some(key_path) = db.lookup_path(&query) {
let x_accel_path = state.keys_dir.join(&key_path).to_string_lossy().to_string();
let x_accel_path = state.keys_external_dir.join(&key_path).to_string_lossy().to_string();
return MyResponse::x_accel_redirect(x_accel_path, &fp);
}
}
@ -230,7 +230,7 @@ fn key_has_uids(state: &HagridState, db: &KeyDatabase, query: &Query)
use sequoia_openpgp::Packet;
use sequoia_openpgp::parse::{Parse, PacketParser, PacketParserResult};
let mut ppr = match db.lookup_path(query) {
Some(path) => PacketParser::from_file(&state.keys_dir.join(path))?,
Some(path) => PacketParser::from_file(&state.keys_external_dir.join(path))?,
None => return Err(failure::err_msg("key vanished")),
};
@ -389,22 +389,23 @@ fn rocket_factory(rocket: rocket::Rocket) -> Result<rocket::Rocket> {
}
fn configure_db_service(config: &Config) -> Result<KeyDatabase> {
let keys_dir: PathBuf = config.get_str("keys_dir")?.into();
let keys_internal_dir: PathBuf = config.get_str("keys_internal_dir")?.into();
let keys_external_dir: PathBuf = config.get_str("keys_external_dir")?.into();
let tmp_dir: PathBuf = config.get_str("tmp_dir")?.into();
let fs_db = KeyDatabase::new(keys_dir, tmp_dir)?;
let fs_db = KeyDatabase::new(keys_internal_dir, keys_external_dir, tmp_dir)?;
Ok(fs_db)
}
fn configure_hagrid_state(config: &Config) -> Result<HagridState> {
let assets_dir: PathBuf = config.get_str("assets_dir")?.into();
let keys_dir: PathBuf = config.get_str("keys_dir")?.into();
let keys_external_dir: PathBuf = config.get_str("keys_external_dir")?.into();
// State
let base_uri = config.get_str("base-URI")?.to_string();
Ok(HagridState {
assets_dir,
keys_dir: keys_dir,
keys_external_dir: keys_external_dir,
base_uri: base_uri.clone(),
x_accel_redirect: config.get_bool("x-accel-redirect")?,
})
@ -495,7 +496,8 @@ pub mod tests {
.extra("assets_dir",
::std::env::current_dir().unwrap().join("dist/assets")
.to_str().unwrap())
.extra("keys_dir", base_dir.join("keys").to_str().unwrap())
.extra("keys_internal_dir", base_dir.join("keys_internal").to_str().unwrap())
.extra("keys_external_dir", base_dir.join("keys_external").to_str().unwrap())
.extra("tmp_dir", base_dir.join("tmp").to_str().unwrap())
.extra("token_dir", base_dir.join("tokens").to_str().unwrap())
.extra("base-URI", BASE_URI)