add simple authentication by secret
Some checks are pending
continuous-integration/drone/push Build is running
Some checks are pending
continuous-integration/drone/push Build is running
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1903,6 +1903,7 @@ dependencies = [
|
|||||||
"actix-web",
|
"actix-web",
|
||||||
"clap",
|
"clap",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"futures",
|
||||||
"log",
|
"log",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"zoidberg_lib",
|
"zoidberg_lib",
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use zoidberg_lib::types::{FetchResponse, Job, RegisterResponse, Status, Update};
|
|||||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
fn build_client(secret: &str) -> Client {
|
fn build_client(secret: &str) -> Client {
|
||||||
let cookie = format!("secret={}", secret);
|
let cookie = format!("{}", secret);
|
||||||
|
|
||||||
let mut headers = header::HeaderMap::new();
|
let mut headers = header::HeaderMap::new();
|
||||||
headers.insert(
|
headers.insert(
|
||||||
@@ -31,11 +31,12 @@ fn build_client(secret: &str) -> Client {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Worker {
|
struct Worker {
|
||||||
id: i32,
|
id: i32,
|
||||||
|
secret: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Worker {
|
impl Worker {
|
||||||
async fn new(server: &str) -> Result<Worker, Box<dyn Error>> {
|
async fn new(server: &str, secret: &str) -> Result<Worker, Box<dyn Error>> {
|
||||||
let res = build_client("some_secret")
|
let res = build_client(secret)
|
||||||
.get(format!("{}/register", server))
|
.get(format!("{}/register", server))
|
||||||
.send()
|
.send()
|
||||||
.await?;
|
.await?;
|
||||||
@@ -43,7 +44,10 @@ impl Worker {
|
|||||||
let body = res.text().await?;
|
let body = res.text().await?;
|
||||||
let r: RegisterResponse = serde_json::from_str(&body)?;
|
let r: RegisterResponse = serde_json::from_str(&body)?;
|
||||||
log::info!("registered worker with id: {}", &r.id);
|
log::info!("registered worker with id: {}", &r.id);
|
||||||
Ok(Worker { id: r.id })
|
Ok(Worker {
|
||||||
|
id: r.id,
|
||||||
|
secret: secret.to_string(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update(self: &Self, jobs: &[Job]) -> Result<(), Box<dyn Error>> {
|
async fn update(self: &Self, jobs: &[Job]) -> Result<(), Box<dyn Error>> {
|
||||||
@@ -56,7 +60,7 @@ impl Worker {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let body = build_client("some_secret")
|
let body = build_client(&self.secret)
|
||||||
.post("http://localhost:8080/update")
|
.post("http://localhost:8080/update")
|
||||||
.json(&updates)
|
.json(&updates)
|
||||||
.send()
|
.send()
|
||||||
@@ -69,7 +73,7 @@ impl Worker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn fetch(self: &Self) -> Result<FetchResponse, Box<dyn Error>> {
|
async fn fetch(self: &Self) -> Result<FetchResponse, Box<dyn Error>> {
|
||||||
let res = build_client("some_secret")
|
let res = build_client(&self.secret)
|
||||||
.get("http://localhost:8080/fetch")
|
.get("http://localhost:8080/fetch")
|
||||||
.send()
|
.send()
|
||||||
.await?;
|
.await?;
|
||||||
@@ -125,8 +129,12 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
let server = matches.value_of("server").unwrap();
|
let server = matches.value_of("server").unwrap();
|
||||||
|
let secret = std::env::var("ZOIDBERG_SECRET")
|
||||||
|
.expect("Please set the $ZOIDBERG_SECRET environment variable");
|
||||||
|
|
||||||
let client = Worker::new(server).await.expect("Could not create client");
|
let client = Worker::new(server, &secret)
|
||||||
|
.await
|
||||||
|
.expect("Could not create client");
|
||||||
|
|
||||||
let pause = time::Duration::from_secs(1);
|
let pause = time::Duration::from_secs(1);
|
||||||
let long_pause = time::Duration::from_secs(20);
|
let long_pause = time::Duration::from_secs(20);
|
||||||
|
|||||||
@@ -15,3 +15,4 @@ serde_json = "1.0"
|
|||||||
clap = "3.2"
|
clap = "3.2"
|
||||||
env_logger = "0.9"
|
env_logger = "0.9"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
futures = "0.3.24"
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder, Result};
|
use actix_web::error::ErrorBadRequest;
|
||||||
|
use actix_web::{
|
||||||
|
dev, get, middleware::Logger, post, web, App, Error, FromRequest, HttpRequest, HttpResponse,
|
||||||
|
HttpServer, Responder, Result,
|
||||||
|
};
|
||||||
use clap;
|
use clap;
|
||||||
use env_logger::Env;
|
use env_logger::Env;
|
||||||
|
use futures::future::{err, ok, Ready};
|
||||||
use log;
|
use log;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use zoidberg_lib::types::{FetchResponse, Job, RegisterResponse, StatusRequest, Update, Worker};
|
use zoidberg_lib::types::{FetchResponse, Job, RegisterResponse, StatusRequest, Update, Worker};
|
||||||
@@ -17,6 +22,41 @@ struct State {
|
|||||||
jobs: Mutex<Vec<Job>>,
|
jobs: Mutex<Vec<Job>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
counter_workers: Mutex::new(0),
|
||||||
|
counter_jobs: Mutex::new(0),
|
||||||
|
workers: Mutex::new(Vec::new()),
|
||||||
|
new_jobs: Mutex::new(Vec::new()),
|
||||||
|
jobs: Mutex::new(Vec::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Authorization {}
|
||||||
|
|
||||||
|
impl FromRequest for Authorization {
|
||||||
|
type Error = Error;
|
||||||
|
type Future = Ready<Result<Self, Self::Error>>;
|
||||||
|
|
||||||
|
fn from_request(req: &HttpRequest, _payload: &mut dev::Payload) -> Self::Future {
|
||||||
|
if let Some(head) = req.headers().get("cookie") {
|
||||||
|
if let Ok(cookie) = head.to_str() {
|
||||||
|
if let Some(secret) = req.app_data::<String>() {
|
||||||
|
println!("{} == {}", secret, cookie);
|
||||||
|
if secret == cookie {
|
||||||
|
return ok(Authorization {});
|
||||||
|
} else {
|
||||||
|
return err(ErrorBadRequest("no auth"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err(ErrorBadRequest("no auth"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
async fn index(data: web::Data<State>) -> impl Responder {
|
async fn index(data: web::Data<State>) -> impl Responder {
|
||||||
let workers = data.workers.lock().unwrap();
|
let workers = data.workers.lock().unwrap();
|
||||||
@@ -26,7 +66,7 @@ async fn index(data: web::Data<State>) -> impl Responder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[get("/register")]
|
#[get("/register")]
|
||||||
async fn register(data: web::Data<State>) -> Result<impl Responder> {
|
async fn register(data: web::Data<State>, _: Authorization) -> Result<impl Responder> {
|
||||||
let mut counter_workers = data.counter_workers.lock().unwrap();
|
let mut counter_workers = data.counter_workers.lock().unwrap();
|
||||||
*counter_workers += 1;
|
*counter_workers += 1;
|
||||||
|
|
||||||
@@ -42,7 +82,7 @@ async fn register(data: web::Data<State>) -> Result<impl Responder> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[get("/fetch")]
|
#[get("/fetch")]
|
||||||
async fn fetch(data: web::Data<State>) -> Result<impl Responder> {
|
async fn fetch(data: web::Data<State>, _: Authorization) -> Result<impl Responder> {
|
||||||
let mut new_jobs = data.new_jobs.lock().unwrap();
|
let mut new_jobs = data.new_jobs.lock().unwrap();
|
||||||
if let Some(j) = new_jobs.pop() {
|
if let Some(j) = new_jobs.pop() {
|
||||||
return Ok(web::Json(FetchResponse::Jobs(vec![j])));
|
return Ok(web::Json(FetchResponse::Jobs(vec![j])));
|
||||||
@@ -54,6 +94,7 @@ async fn fetch(data: web::Data<State>) -> Result<impl Responder> {
|
|||||||
async fn status(
|
async fn status(
|
||||||
s: web::Json<Vec<StatusRequest>>,
|
s: web::Json<Vec<StatusRequest>>,
|
||||||
data: web::Data<State>,
|
data: web::Data<State>,
|
||||||
|
_: Authorization,
|
||||||
) -> Result<impl Responder> {
|
) -> Result<impl Responder> {
|
||||||
let jobs = data.jobs.lock().unwrap();
|
let jobs = data.jobs.lock().unwrap();
|
||||||
let status_updates: Vec<Job> = jobs
|
let status_updates: Vec<Job> = jobs
|
||||||
@@ -66,7 +107,11 @@ async fn status(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[post("/update")]
|
#[post("/update")]
|
||||||
async fn update(updates: web::Json<Vec<Update>>, data: web::Data<State>) -> Result<String> {
|
async fn update(
|
||||||
|
updates: web::Json<Vec<Update>>,
|
||||||
|
data: web::Data<State>,
|
||||||
|
_: Authorization,
|
||||||
|
) -> Result<String> {
|
||||||
let mut jobs = data.jobs.lock().unwrap();
|
let mut jobs = data.jobs.lock().unwrap();
|
||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
for update in updates.iter() {
|
for update in updates.iter() {
|
||||||
@@ -87,7 +132,11 @@ async fn update(updates: web::Json<Vec<Update>>, data: web::Data<State>) -> Resu
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[post("/submit")]
|
#[post("/submit")]
|
||||||
async fn submit(data: web::Data<State>, js: web::Json<Vec<Job>>) -> Result<impl Responder> {
|
async fn submit(
|
||||||
|
data: web::Data<State>,
|
||||||
|
js: web::Json<Vec<Job>>,
|
||||||
|
_: Authorization,
|
||||||
|
) -> Result<impl Responder> {
|
||||||
let mut new_jobs = data.new_jobs.lock().unwrap();
|
let mut new_jobs = data.new_jobs.lock().unwrap();
|
||||||
let mut jobs = data.jobs.lock().unwrap();
|
let mut jobs = data.jobs.lock().unwrap();
|
||||||
let mut counter_jobs = data.counter_jobs.lock().unwrap();
|
let mut counter_jobs = data.counter_jobs.lock().unwrap();
|
||||||
@@ -113,21 +162,20 @@ async fn submit(data: web::Data<State>, js: web::Json<Vec<Job>>) -> Result<impl
|
|||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
env_logger::Builder::from_env(Env::default().default_filter_or("zoidberg_server=info")).init();
|
env_logger::Builder::from_env(Env::default().default_filter_or("zoidberg_server=info")).init();
|
||||||
|
|
||||||
|
let secret = std::env::var("ZOIDBERG_SECRET")
|
||||||
|
.expect("Please set the $ZOIDBERG_SECRET environment variable");
|
||||||
|
|
||||||
let _matches = clap::App::new("Zoidberg server")
|
let _matches = clap::App::new("Zoidberg server")
|
||||||
.version(VERSION)
|
.version(VERSION)
|
||||||
.author("Johannes Heuel")
|
.author("Johannes Heuel")
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let state = web::Data::new(State {
|
let state = web::Data::new(State::new());
|
||||||
counter_workers: Mutex::new(0),
|
|
||||||
counter_jobs: Mutex::new(0),
|
|
||||||
workers: Mutex::new(Vec::new()),
|
|
||||||
new_jobs: Mutex::new(Vec::new()),
|
|
||||||
jobs: Mutex::new(Vec::new()),
|
|
||||||
});
|
|
||||||
|
|
||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
App::new()
|
App::new()
|
||||||
|
.wrap(Logger::default())
|
||||||
|
.app_data(secret.clone())
|
||||||
.app_data(state.clone())
|
.app_data(state.clone())
|
||||||
.service(index)
|
.service(index)
|
||||||
.service(register)
|
.service(register)
|
||||||
@@ -151,13 +199,7 @@ mod tests {
|
|||||||
async fn test_index() {
|
async fn test_index() {
|
||||||
let app = test::init_service(
|
let app = test::init_service(
|
||||||
App::new()
|
App::new()
|
||||||
.app_data(web::Data::new(State {
|
.app_data(web::Data::new(State::new()))
|
||||||
counter_workers: Mutex::new(0),
|
|
||||||
counter_jobs: Mutex::new(0),
|
|
||||||
workers: Mutex::new(Vec::new()),
|
|
||||||
new_jobs: Mutex::new(Vec::new()),
|
|
||||||
jobs: Mutex::new(Vec::new()),
|
|
||||||
}))
|
|
||||||
.service(index),
|
.service(index),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
@@ -170,17 +212,15 @@ mod tests {
|
|||||||
async fn test_register() {
|
async fn test_register() {
|
||||||
let app = test::init_service(
|
let app = test::init_service(
|
||||||
App::new()
|
App::new()
|
||||||
.app_data(web::Data::new(State {
|
.app_data(String::from("secret"))
|
||||||
counter_workers: Mutex::new(0),
|
.app_data(web::Data::new(State::new()))
|
||||||
counter_jobs: Mutex::new(0),
|
|
||||||
workers: Mutex::new(Vec::new()),
|
|
||||||
new_jobs: Mutex::new(Vec::new()),
|
|
||||||
jobs: Mutex::new(Vec::new()),
|
|
||||||
}))
|
|
||||||
.service(register),
|
.service(register),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let req = test::TestRequest::get().uri("/register").to_request();
|
let req = test::TestRequest::get()
|
||||||
|
.append_header(("cookie", "secret"))
|
||||||
|
.uri("/register")
|
||||||
|
.to_request();
|
||||||
let resp: RegisterResponse = test::call_and_read_body_json(&app, req).await;
|
let resp: RegisterResponse = test::call_and_read_body_json(&app, req).await;
|
||||||
assert_eq!(resp.id, 1);
|
assert_eq!(resp.id, 1);
|
||||||
}
|
}
|
||||||
@@ -190,6 +230,7 @@ mod tests {
|
|||||||
let cmd = String::from("hi");
|
let cmd = String::from("hi");
|
||||||
let app = test::init_service(
|
let app = test::init_service(
|
||||||
App::new()
|
App::new()
|
||||||
|
.app_data(String::from("secret"))
|
||||||
.app_data(web::Data::new(State {
|
.app_data(web::Data::new(State {
|
||||||
counter_workers: Mutex::new(0),
|
counter_workers: Mutex::new(0),
|
||||||
counter_jobs: Mutex::new(0),
|
counter_jobs: Mutex::new(0),
|
||||||
@@ -204,7 +245,10 @@ mod tests {
|
|||||||
.service(fetch),
|
.service(fetch),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let req = test::TestRequest::get().uri("/fetch").to_request();
|
let req = test::TestRequest::get()
|
||||||
|
.append_header(("cookie", "secret"))
|
||||||
|
.uri("/fetch")
|
||||||
|
.to_request();
|
||||||
let resp: FetchResponse = test::call_and_read_body_json(&app, req).await;
|
let resp: FetchResponse = test::call_and_read_body_json(&app, req).await;
|
||||||
match resp {
|
match resp {
|
||||||
FetchResponse::Nop => {
|
FetchResponse::Nop => {
|
||||||
@@ -225,6 +269,7 @@ mod tests {
|
|||||||
let cmd = String::from("hi");
|
let cmd = String::from("hi");
|
||||||
let app = test::init_service(
|
let app = test::init_service(
|
||||||
App::new()
|
App::new()
|
||||||
|
.app_data(String::from("secret"))
|
||||||
.app_data(web::Data::new(State {
|
.app_data(web::Data::new(State {
|
||||||
counter_workers: Mutex::new(0),
|
counter_workers: Mutex::new(0),
|
||||||
counter_jobs: Mutex::new(0),
|
counter_jobs: Mutex::new(0),
|
||||||
@@ -240,6 +285,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let req = test::TestRequest::post()
|
let req = test::TestRequest::post()
|
||||||
|
.append_header(("cookie", "secret"))
|
||||||
.set_json(vec![StatusRequest { id: 1 }])
|
.set_json(vec![StatusRequest { id: 1 }])
|
||||||
.uri("/status")
|
.uri("/status")
|
||||||
.to_request();
|
.to_request();
|
||||||
@@ -251,17 +297,13 @@ mod tests {
|
|||||||
async fn test_update() {
|
async fn test_update() {
|
||||||
let app = test::init_service(
|
let app = test::init_service(
|
||||||
App::new()
|
App::new()
|
||||||
.app_data(web::Data::new(State {
|
.app_data(String::from("secret"))
|
||||||
counter_workers: Mutex::new(0),
|
.app_data(web::Data::new(State::new()))
|
||||||
counter_jobs: Mutex::new(0),
|
|
||||||
workers: Mutex::new(Vec::new()),
|
|
||||||
new_jobs: Mutex::new(Vec::new()),
|
|
||||||
jobs: Mutex::new(Vec::new()),
|
|
||||||
}))
|
|
||||||
.service(update),
|
.service(update),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let req = test::TestRequest::post()
|
let req = test::TestRequest::post()
|
||||||
|
.append_header(("cookie", "secret"))
|
||||||
.set_json(vec![Update {
|
.set_json(vec![Update {
|
||||||
worker: 0,
|
worker: 0,
|
||||||
job: 0,
|
job: 0,
|
||||||
@@ -277,17 +319,13 @@ mod tests {
|
|||||||
async fn test_submit() {
|
async fn test_submit() {
|
||||||
let app = test::init_service(
|
let app = test::init_service(
|
||||||
App::new()
|
App::new()
|
||||||
.app_data(web::Data::new(State {
|
.app_data(String::from("secret"))
|
||||||
counter_workers: Mutex::new(0),
|
.app_data(web::Data::new(State::new()))
|
||||||
counter_jobs: Mutex::new(0),
|
|
||||||
workers: Mutex::new(Vec::new()),
|
|
||||||
new_jobs: Mutex::new(Vec::new()),
|
|
||||||
jobs: Mutex::new(Vec::new()),
|
|
||||||
}))
|
|
||||||
.service(submit),
|
.service(submit),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let req = test::TestRequest::post()
|
let req = test::TestRequest::post()
|
||||||
|
.append_header(("cookie", "secret"))
|
||||||
.set_json(vec![Job {
|
.set_json(vec![Job {
|
||||||
id: 0,
|
id: 0,
|
||||||
cmd: String::from("hi"),
|
cmd: String::from("hi"),
|
||||||
|
|||||||
Reference in New Issue
Block a user