mirror of
https://github.com/narrrl/narl-workspace.git
synced 2026-11-04 17:07:00 +01:00
auth, headers: the examples are refused, HTTPS is insisted on
The server no longer starts with WORKSPACE_SECRET or WORKSPACE_PASSWORD left at the value .env.example ships with. The secret was only checked for length, and the public placeholder passed: anyone who had read the repository could sign a session cookie for themselves. A secret under 32 characters is warned about. With WORKSPACE_SECURE_COOKIE=1 the cookie is named __Host-diary_session, which the browser keeps to this host and to HTTPS and which no sibling subdomain can plant; turning it on logs everyone out once. Responses then carry Strict-Transport-Security for a year. The traefik example turns it on. The password is compared as an HMAC under the secret, so the time a comparison takes no longer depends on the configured password's length. Every response also carries Cross-Origin-Opener-Policy and Cross-Origin-Resource-Policy same-origin and a Permissions-Policy that turns camera, microphone, location, payment and USB off; API answers are no-store unless they say otherwise.
This commit is contained in:
1 parent
6bf88e7ffd
commit
f450883ac0
6 files changed
+128
-19
No files matched your search
+16
-5
@@ -4,6 +4,10 @@ use anyhow::{Context, Result};
|
||||
use chrono::Weekday;
|
||||
use chrono_tz::Tz;
|
||||
|
||||
/// The placeholders `.env.example` ships with, refused when left in place.
|
||||
const EXAMPLE_SECRET: &str = "replace-with-32-random-characters";
|
||||
const EXAMPLE_PASSWORD: &str = "change-me";
|
||||
|
||||
/// Runtime configuration. Everything comes from the environment (`.env` is
|
||||
/// loaded on startup), because this is a deliberately single-user application.
|
||||
#[derive(Clone)]
|
||||
@@ -251,13 +255,20 @@ impl Config {
|
||||
if secret.len() < 16 {
|
||||
anyhow::bail!("WORKSPACE_SECRET must be at least 16 characters");
|
||||
}
|
||||
|
||||
if password == "change-me" {
|
||||
tracing::warn!(
|
||||
"WORKSPACE_PASSWORD is still the example value from .env.example — \
|
||||
anyone who can reach this server can read the workspace"
|
||||
// The examples are public: with the secret anyone can sign a session
|
||||
// cookie, with the password anyone can log in.
|
||||
if secret == EXAMPLE_SECRET.as_bytes() {
|
||||
anyhow::bail!(
|
||||
"WORKSPACE_SECRET is still the example from .env.example — \
|
||||
set it to something random: openssl rand -base64 32"
|
||||
);
|
||||
}
|
||||
if secret.len() < 32 {
|
||||
tracing::warn!("WORKSPACE_SECRET is shorter than 32 characters; a longer one is safer");
|
||||
}
|
||||
if password == EXAMPLE_PASSWORD {
|
||||
anyhow::bail!("WORKSPACE_PASSWORD is still the example from .env.example — change it");
|
||||
}
|
||||
|
||||
let bind = var("BIND")
|
||||
.unwrap_or_else(|| "127.0.0.1:4242".to_string())
|
||||
|
||||
Reference in new issue
Block a user