Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LLT-5882: Refactor teliod cgi structure #1047

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added .unreleased/LLT-5882
Empty file.
5 changes: 5 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ black fix="false":
pylint:
docker run --rm -t -v$(pwd):/code 'ubuntu:22.04' sh -c "apt-get update && apt-get -y install python3-pip && cd code && pip3 install --no-deps -r requirements.txt && pipenv install --system && cd nat-lab && pipenv install --system && pylint -f colorized . --ignore telio_bindings.py"

# Start a dev web cgi server, for local teliod cgi development
web:
@echo "Go to http://127.0.0.1:8080/cgi-bin/teliod.cgi"
python3 -m http.server --cgi -d $(pwd)/contrib/http_root/ -b 127.0.0.1 8080

_udeps-install: _nightly-install
cargo +{{ nightly }} install [email protected] --locked

Expand Down
File renamed without changes.
3 changes: 2 additions & 1 deletion clis/teliod/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,5 @@ rand = "0.8.5"
serial_test = "3.2.0"

[features]
qnap = ["const_format", "rust-cgi"]
cgi = ["const_format", "rust-cgi"]
qnap = ["cgi"]
48 changes: 22 additions & 26 deletions clis/teliod/src/qnap.rs → clis/teliod/src/cgi/api.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,25 @@
use core::str;
use std::{
fs,
io::Write,
process::{Command, Stdio},
str,
};

use const_format::concatcp;
use rust_cgi::{http::Method, http::StatusCode, text_response, Request, Response};
use rust_cgi::{
http::{Method, StatusCode},
text_response, Response,
};

use crate::{
command_listener::CommandResponse,
config::{TeliodDaemonConfig, TeliodDaemonConfigPartial},
ClientCmd, DaemonSocket, TeliodError, TIMEOUT_SEC,
};

const QPKG_DIR: &str = "/share/CACHEDEV1_DATA/.qpkg/NordSecurityMeshnet";
const TELIOD_BIN: &str = concatcp!(QPKG_DIR, "/teliod");
const MESHNET_LOG: &str = concatcp!(QPKG_DIR, "/meshnet.log");
const TELIOD_LOG: &str = "/var/log/teliod.log";

#[cfg(not(test))]
const TELIOD_CFG: &str = concatcp!(QPKG_DIR, "/teliod.cfg");
#[cfg(test)]
use tests::TELIOD_CFG;
use super::{
constants::{MESHNET_LOG, TELIOD_BIN, TELIOD_CFG, TELIOD_LOG},
CgiRequest,
};

macro_rules! teliod_blocking_query {
($command:expr) => {{
Expand All @@ -37,26 +34,26 @@ macro_rules! teliod_blocking_query {
}};
}

pub(crate) fn handle_request(request: Request) -> Response {
match (request.method(), request.uri().query()) {
(&Method::POST, _) => start_daemon(),
(&Method::DELETE, _) => stop_daemon(),
(&Method::PATCH, _) => {
pub(crate) fn handle_api(request: &CgiRequest) -> Option<Response> {
match (request.method(), request.route()) {
(&Method::POST, "" | "/") => Some(start_daemon()),
(&Method::DELETE, "" | "/") => Some(stop_daemon()),
(&Method::PATCH, "" | "/") => {
let body = match str::from_utf8(request.body()) {
Ok(body) => body,
Err(error) => {
return text_response(
return Some(text_response(
StatusCode::BAD_REQUEST,
format!("Invalid UTF-8 in request body: {}", error),
)
))
}
};
update_config(body)
Some(update_config(body))
}
(&Method::GET, Some("info=get-status")) => get_status(),
(&Method::GET, Some("info=get-teliod-logs")) => get_teliod_logs(),
(&Method::GET, Some("info=get-meshnet-logs")) => get_meshnet_logs(),
(_, _) => text_response(StatusCode::BAD_REQUEST, "Invalid request."),
(&Method::GET, "/get-status") => Some(get_status()),
(&Method::GET, "/get-teliod-logs") => Some(get_teliod_logs()),
(&Method::GET, "/get-meshnet-logs") => Some(get_meshnet_logs()),
(_, _) => Some(text_response(StatusCode::BAD_REQUEST, "Invalid request.")),
}
}

Expand Down Expand Up @@ -237,12 +234,11 @@ mod tests {

use super::{update_config, TeliodDaemonConfig};
use crate::{
cgi::constants::TELIOD_CFG,
config::{InterfaceConfig, MqttConfig, Percentage},
configure_interface::InterfaceConfigurationProvider,
};

pub const TELIOD_CFG: &str = "/tmp/teliod_config.json";

#[test]
#[serial]
fn test_update_config() {
Expand Down
15 changes: 15 additions & 0 deletions clis/teliod/src/cgi/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use const_format::concatcp;

#[cfg(feature = "qnap")]
pub const APP_DIR: &str = "/share/CACHEDEV1_DATA/.qpkg/NordSecurityMeshnet";
#[cfg(not(feature = "qnap"))]
pub const APP_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/target/debug");

pub const TELIOD_BIN: &str = concatcp!(APP_DIR, "/teliod");
pub const MESHNET_LOG: &str = concatcp!(APP_DIR, "/meshnet.log");
pub const TELIOD_LOG: &str = "/var/log/teliod.log";

#[cfg(not(test))]
pub const TELIOD_CFG: &str = concatcp!(APP_DIR, "/teliod.cfg");
#[cfg(test)]
pub const TELIOD_CFG: &str = "/tmp/teliod_config.json";
73 changes: 73 additions & 0 deletions clis/teliod/src/cgi/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use std::{env::var, ops::Deref};

use rust_cgi::{http::StatusCode, text_response, Request, Response};

mod api;
pub(crate) mod constants;

pub struct CgiRequest {
pub inner: Request,
route: String,
}

impl CgiRequest {
fn new(inner: Request) -> Self {
Self {
inner,
route: var("PATH_INFO").unwrap_or_default(),
}
}

pub fn route(&self) -> &str {
&self.route
}
}

impl Deref for CgiRequest {
type Target = Request;
fn deref(&self) -> &Self::Target {
&self.inner
}
}

pub fn handle_request(request: Request) -> Response {
let request = CgiRequest::new(request);

if let Some(response) = api::handle_api(&request) {
#[cfg(debug_assertions)]
let response = trace_request(&request, &response).unwrap_or(text_response(
StatusCode::INTERNAL_SERVER_ERROR,
"Tracing request failed.",
));
return response;
}

text_response(StatusCode::BAD_REQUEST, "Invalid request.")
}

#[cfg(debug_assertions)]
fn trace_request(request: &CgiRequest, response: &Response) -> Option<Response> {
use std::{env::vars, fmt::Write};
let mut msg = String::new();
let _ = writeln!(
&mut msg,
"ENVIRONMENT:\n{:#?}\n",
vars().collect::<Vec<_>>(),
);
let _ = writeln!(
&mut msg,
"REQUEST:\nmethod: {:?}\nuri: {:?}\npath: {:?}\nroute: {:?}\nquery: {:?}\n",
request.method(),
request.uri(),
request.uri().path(),
request.route(),
request.uri().query(),
);
let _ = writeln!(
&mut msg,
"RESPONSE:\nstatus_code: {:?}\nbody: {:?}\n",
response.status(),
std::str::from_utf8(response.body()).unwrap_or("[Error] Response with invalid UTF-8."),
);
Some(text_response(StatusCode::OK, msg))
}
16 changes: 8 additions & 8 deletions clis/teliod/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ use tokio::{
};
use tracing::{debug, error};

#[cfg(feature = "cgi")]
mod cgi;
mod command_listener;
mod comms;
mod config;
mod configure_interface;
mod core_api;
mod daemon;
mod nc;
#[cfg(feature = "qnap")]
mod qnap;

use crate::{
command_listener::CommandResponse,
Expand Down Expand Up @@ -50,9 +50,9 @@ enum Cmd {
Daemon { config_path: String },
#[clap(flatten)]
Client(ClientCmd),
#[cfg(feature = "qnap")]
#[cfg(feature = "cgi")]
#[clap(about = "Receive and parse http requests")]
QnapCgi,
Cgi,
}

#[derive(Debug, ThisError)]
Expand All @@ -63,7 +63,7 @@ enum TeliodError {
InvalidCommand(String),
#[error("Invalid response received: {0}")]
InvalidResponse(String),
#[error("Client failed to receive response in {TIMEOUT_SEC}")]
#[error("Client failed to receive response in {TIMEOUT_SEC}s")]
ClientTimeoutError,
#[error("Broken signal stream")]
BrokenSignalStream,
Expand Down Expand Up @@ -149,9 +149,9 @@ async fn main() -> Result<(), TeliodError> {
Err(TeliodError::DaemonIsNotRunning)
}
}
#[cfg(feature = "qnap")]
Cmd::QnapCgi => {
rust_cgi::handle(qnap::handle_request);
#[cfg(feature = "cgi")]
Cmd::Cgi => {
rust_cgi::handle(cgi::handle_request);
Ok(())
}
}
Expand Down
1 change: 1 addition & 0 deletions contrib/http_root/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**/*.log
17 changes: 17 additions & 0 deletions contrib/http_root/cgi-bin/teliod.cgi
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash

set -eu -o pipefail

fail() {
cat $DEV_DIR/cargo.log
exit 0
}

DEV_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BIN_DIR="$(realpath $DEV_DIR/../../../target/debug/)"

cargo build -F cgi -p teliod >"$DEV_DIR/cargo.log" 2>&1 || fail

export PATH=$BIN_DIR:$PATH

exec teliod cgi
2 changes: 1 addition & 1 deletion qnap/build_sign.csv
Original file line number Diff line number Diff line change
@@ -1 +1 @@
,/NordSecMeshnet.sh,
,/NordSecurityMeshnet.sh,
2 changes: 1 addition & 1 deletion qnap/qpkg.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ QPKG_LICENSE="GPL-3.0-only"
# Preferred number in start/stop sequence.
QPKG_RC_NUM="101"
# Init-script used to control the start and stop of the installed application.
QPKG_SERVICE_PROGRAM="NordSecMeshnet.sh"
QPKG_SERVICE_PROGRAM="NordSecurityMeshnet.sh"

# Optional 1 is enable. Path of starting/ stopping shall script. (no start/stop on App Center)
#QPKG_DISABLE_APPCENTER_UI_SERVICE=1
Expand Down
61 changes: 0 additions & 61 deletions qnap/shared/NordSecMeshnet.sh

This file was deleted.

Loading
Loading