Compare commits
7 commits
feat-nginx
...
master
Author | SHA1 | Date | |
---|---|---|---|
Aravinth Manivannan | b0d94f91dc | ||
Aravinth Manivannan | d40e8642de | ||
Aravinth Manivannan | 5851b686b4 | ||
Aravinth Manivannan | db9115b90b | ||
Aravinth Manivannan | b15c72ef30 | ||
Aravinth Manivannan | cd0589fb2e | ||
Aravinth Manivannan | 58eef6b3fa |
27
Cargo.lock
generated
27
Cargo.lock
generated
|
@ -208,6 +208,18 @@ dependencies = [
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "actix-web-prom"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9df3127d20a5d01c9fc9aceb969a38d31a6767e1b48a54d55a8f56c769a84923"
|
||||||
|
dependencies = [
|
||||||
|
"actix-web",
|
||||||
|
"futures-core",
|
||||||
|
"pin-project-lite",
|
||||||
|
"prometheus",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "adler"
|
name = "adler"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
|
@ -415,6 +427,7 @@ dependencies = [
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"actix-web-codegen-const-routes",
|
"actix-web-codegen-const-routes",
|
||||||
"actix-web-httpauth",
|
"actix-web-httpauth",
|
||||||
|
"actix-web-prom",
|
||||||
"base64",
|
"base64",
|
||||||
"clap",
|
"clap",
|
||||||
"config",
|
"config",
|
||||||
|
@ -1408,6 +1421,20 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prometheus"
|
||||||
|
version = "0.13.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"fnv",
|
||||||
|
"lazy_static",
|
||||||
|
"memchr",
|
||||||
|
"parking_lot 0.12.1",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-error"
|
name = "quick-error"
|
||||||
version = "1.2.3"
|
version = "1.2.3"
|
||||||
|
|
|
@ -12,6 +12,7 @@ build = "build.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "4"
|
actix-web = "4"
|
||||||
|
actix-web-prom = "0.6.0"
|
||||||
futures-util = { version = "0.3.17", default-features = false, features = ["std"] }
|
futures-util = { version = "0.3.17", default-features = false, features = ["std"] }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
|
|
|
@ -3,8 +3,7 @@ source_code = "https://git.batsense.net/librepages/conductor"
|
||||||
conductor = "dummy"
|
conductor = "dummy"
|
||||||
|
|
||||||
[creds]
|
[creds]
|
||||||
username = "librepages_api"
|
token="longrandomlygeneratedpassword"
|
||||||
password="longrandomlygeneratedpassword"
|
|
||||||
|
|
||||||
[server]
|
[server]
|
||||||
# Please set a unique value, your mCaptcha instance's security depends on this being
|
# Please set a unique value, your mCaptcha instance's security depends on this being
|
||||||
|
|
24
contrib/librepages-conductor.service
Normal file
24
contrib/librepages-conductor.service
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
[Unit]
|
||||||
|
Description=LibrePages Conductor: Easiest way to deploy websites. Conductor component
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=root
|
||||||
|
ExecStart=/usr/bin/conductor serve
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=1
|
||||||
|
SuccessExitStatus=3 4
|
||||||
|
RestartForceExitStatus=3 4
|
||||||
|
SystemCallArchitectures=native
|
||||||
|
MemoryDenyWriteExecute=true
|
||||||
|
NoNewPrivileges=true
|
||||||
|
Environment="RUST_LOG=info"
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Wants=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
Requires=postgresql.service
|
||||||
|
After=syslog.target
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
|
@ -38,6 +38,8 @@ DOCKER_IMG="realaravinth/$NAME:$3"
|
||||||
|
|
||||||
get_bin(){
|
get_bin(){
|
||||||
cp target/release/conductor $TARGET_DIR
|
cp target/release/conductor $TARGET_DIR
|
||||||
|
cp -r config/ $TARGET_DIR
|
||||||
|
cp -r contrib/ $TARGET_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
copy() {
|
copy() {
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
use actix_web::dev::ServiceRequest;
|
use actix_web::dev::ServiceRequest;
|
||||||
use actix_web::web;
|
use actix_web::web;
|
||||||
use actix_web::Error;
|
use actix_web::Error;
|
||||||
use actix_web_httpauth::extractors::basic::BasicAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
|
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use crate::AppCtx;
|
use crate::AppCtx;
|
||||||
|
@ -26,14 +26,13 @@ use crate::SETTINGS;
|
||||||
pub mod meta;
|
pub mod meta;
|
||||||
pub mod webhook;
|
pub mod webhook;
|
||||||
|
|
||||||
pub async fn httpauth(
|
pub async fn bearerauth(
|
||||||
req: ServiceRequest,
|
req: ServiceRequest,
|
||||||
credentials: BasicAuth,
|
credentials: BearerAuth,
|
||||||
) -> Result<ServiceRequest, (Error, ServiceRequest)> {
|
) -> Result<ServiceRequest, (Error, ServiceRequest)> {
|
||||||
let _ctx: &AppCtx = req.app_data().unwrap();
|
let _ctx: &AppCtx = req.app_data().unwrap();
|
||||||
let username = credentials.user_id();
|
let token = credentials.token();
|
||||||
let password = credentials.password().unwrap();
|
if SETTINGS.authenticate(token) {
|
||||||
if SETTINGS.authenticate(username, password) {
|
|
||||||
Ok(req)
|
Ok(req)
|
||||||
} else {
|
} else {
|
||||||
let e = Error::from(ServiceError::Unauthorized);
|
let e = Error::from(ServiceError::Unauthorized);
|
||||||
|
|
|
@ -24,7 +24,7 @@ use crate::errors::*;
|
||||||
use crate::AppCtx;
|
use crate::AppCtx;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
use super::httpauth;
|
use super::bearerauth;
|
||||||
|
|
||||||
pub mod routes {
|
pub mod routes {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -47,7 +47,7 @@ pub fn services(cfg: &mut web::ServiceConfig) {
|
||||||
|
|
||||||
#[actix_web_codegen_const_routes::post(
|
#[actix_web_codegen_const_routes::post(
|
||||||
path = "API_V1_ROUTES.webhook.post_event",
|
path = "API_V1_ROUTES.webhook.post_event",
|
||||||
wrap = "HttpAuthentication::basic(httpauth)"
|
wrap = "HttpAuthentication::bearer(bearerauth)"
|
||||||
)]
|
)]
|
||||||
async fn post_event(ctx: AppCtx, payload: web::Json<EventType>) -> ServiceResult<impl Responder> {
|
async fn post_event(ctx: AppCtx, payload: web::Json<EventType>) -> ServiceResult<impl Responder> {
|
||||||
ctx.conductor.process(payload.into_inner()).await;
|
ctx.conductor.process(payload.into_inner()).await;
|
||||||
|
@ -71,10 +71,7 @@ pub mod tests {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let creds = settings.creds.clone();
|
let creds = settings.creds.clone();
|
||||||
let auth = format!(
|
let auth = format!("Bearer {}", creds.token,);
|
||||||
"Basic {}",
|
|
||||||
base64::encode(format!("{}:{}", creds.username.clone(), creds.password))
|
|
||||||
);
|
|
||||||
|
|
||||||
let msg = EventType::NewSite {
|
let msg = EventType::NewSite {
|
||||||
hostname: "demo.librepages.org".into(),
|
hostname: "demo.librepages.org".into(),
|
||||||
|
|
|
@ -19,6 +19,7 @@ use std::env;
|
||||||
use actix_web::http::StatusCode;
|
use actix_web::http::StatusCode;
|
||||||
use actix_web::web::JsonConfig;
|
use actix_web::web::JsonConfig;
|
||||||
use actix_web::{error::InternalError, middleware, App, HttpServer};
|
use actix_web::{error::InternalError, middleware, App, HttpServer};
|
||||||
|
use actix_web_prom::PrometheusMetricsBuilder;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
|
@ -112,6 +113,11 @@ async fn serve(settings: Settings, ctx: AppCtx) -> std::io::Result<()> {
|
||||||
let ip = settings.server.get_ip();
|
let ip = settings.server.get_ip();
|
||||||
println!("Starting server on: http://{ip}");
|
println!("Starting server on: http://{ip}");
|
||||||
|
|
||||||
|
let prometheus = PrometheusMetricsBuilder::new("api")
|
||||||
|
.endpoint("/metrics")
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
App::new()
|
App::new()
|
||||||
.wrap(middleware::Logger::default())
|
.wrap(middleware::Logger::default())
|
||||||
|
@ -124,6 +130,7 @@ async fn serve(settings: Settings, ctx: AppCtx) -> std::io::Result<()> {
|
||||||
middleware::TrailingSlash::Trim,
|
middleware::TrailingSlash::Trim,
|
||||||
))
|
))
|
||||||
.app_data(get_json_err())
|
.app_data(get_json_err())
|
||||||
|
.wrap(prometheus.clone())
|
||||||
.configure(routes::services)
|
.configure(routes::services)
|
||||||
})
|
})
|
||||||
.bind(ip)?
|
.bind(ip)?
|
||||||
|
|
|
@ -54,8 +54,7 @@ pub enum ConductorType {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
pub struct Creds {
|
pub struct Creds {
|
||||||
pub username: String,
|
pub token: String,
|
||||||
pub password: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
@ -69,15 +68,15 @@ pub struct Settings {
|
||||||
|
|
||||||
#[cfg(not(tarpaulin_include))]
|
#[cfg(not(tarpaulin_include))]
|
||||||
impl Settings {
|
impl Settings {
|
||||||
pub fn authenticate(&self, username: &str, password: &str) -> bool {
|
pub fn authenticate(&self, token: &str) -> bool {
|
||||||
self.creds.username == username && self.creds.password == password
|
self.creds.token == token
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new() -> Result<Self, ConfigError> {
|
pub fn new() -> Result<Self, ConfigError> {
|
||||||
let mut s = Config::builder();
|
let mut s = Config::builder();
|
||||||
|
|
||||||
const CURRENT_DIR: &str = "./config/config.toml";
|
const CURRENT_DIR: &str = "./config/config.toml";
|
||||||
const ETC: &str = "/etc/lpconductor/config.toml";
|
const ETC: &str = "/etc/librepages/conductor/config.toml";
|
||||||
|
|
||||||
if let Ok(path) = env::var("LPCONDUCTOR_CONFIG") {
|
if let Ok(path) = env::var("LPCONDUCTOR_CONFIG") {
|
||||||
s = s.add_source(File::with_name(&path));
|
s = s.add_source(File::with_name(&path));
|
||||||
|
@ -138,6 +137,13 @@ fn set_separator_field(mut s: ConfigBuilder<DefaultState>) -> ConfigBuilder<Defa
|
||||||
&format!("{PREFIX}{SEPARATOR}SERVER{SEPARATOR}PROXY_HAS_TLS"),
|
&format!("{PREFIX}{SEPARATOR}SERVER{SEPARATOR}PROXY_HAS_TLS"),
|
||||||
"server.proxy_has_tls",
|
"server.proxy_has_tls",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
s = from_env(
|
||||||
|
s,
|
||||||
|
&format!("{PREFIX}{SEPARATOR}CREDS{SEPARATOR}TOKEN"),
|
||||||
|
"creds.token",
|
||||||
|
);
|
||||||
|
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,16 +154,13 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn creds_works() {
|
fn creds_works() {
|
||||||
let settings = Settings::new().unwrap();
|
let settings = Settings::new().unwrap();
|
||||||
let mut creds = settings.creds.clone();
|
let creds = settings.creds.clone();
|
||||||
|
|
||||||
assert!(settings.authenticate(&creds.username, &creds.password));
|
assert!(settings.authenticate(&creds.token));
|
||||||
|
|
||||||
creds.username = "noexist".into();
|
|
||||||
assert!(!settings.authenticate(&creds.username, &creds.password));
|
|
||||||
|
|
||||||
let mut creds = settings.creds.clone();
|
let mut creds = settings.creds.clone();
|
||||||
|
|
||||||
creds.password = "noexist".into();
|
creds.token = "noexist".into();
|
||||||
assert!(!settings.authenticate(&creds.username, &creds.password));
|
assert!(!settings.authenticate(&creds.token))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue