aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock57
-rw-r--r--Cargo.toml2
-rw-r--r--src/main.rs68
3 files changed, 114 insertions, 13 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 5e31633..9695ee3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -31,7 +31,7 @@ dependencies = [
"actix-tls",
"actix-utils",
"ahash 0.8.3",
- "base64",
+ "base64 0.21.0",
"bitflags",
"brotli",
"bytes",
@@ -204,6 +204,21 @@ dependencies = [
]
[[package]]
+name = "actix-web-httpauth"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6dda62cf04bc3a9ad2ea8f314f721951cfdb4cdacec4e984d20e77c7bb170991"
+dependencies = [
+ "actix-utils",
+ "actix-web",
+ "base64 0.13.1",
+ "futures-core",
+ "futures-util",
+ "log",
+ "pin-project-lite",
+]
+
+[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -264,6 +279,12 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+
+[[package]]
+name = "base64"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
@@ -470,6 +491,7 @@ dependencies = [
"futures-task",
"pin-project-lite",
"pin-utils",
+ "slab",
]
[[package]]
@@ -650,6 +672,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
+name = "memoffset"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -677,6 +708,20 @@ dependencies = [
]
[[package]]
+name = "nix"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "libc",
+ "memoffset",
+ "pin-utils",
+ "static_assertions",
+]
+
+[[package]]
name = "num_cpus"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -854,6 +899,8 @@ name = "rustkrazy_admind"
version = "0.1.0"
dependencies = [
"actix-web",
+ "actix-web-httpauth",
+ "nix",
"rustls",
"rustls-pemfile",
"thiserror",
@@ -877,7 +924,7 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
dependencies = [
- "base64",
+ "base64 0.21.0",
]
[[package]]
@@ -989,6 +1036,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 78ed429..99a27da 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,6 +7,8 @@ edition = "2021"
[dependencies]
actix-web = { version = "4.3.1", features = ["rustls"] }
+actix-web-httpauth = "0.8.0"
+nix = "0.26.2"
rustls = "0.20.0"
rustls-pemfile = "1.0.2"
thiserror = "1.0"
diff --git a/src/main.rs b/src/main.rs
index 1f2c99f..6b058ab 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,14 +3,57 @@ use rustkrazy_admind::{Error, Result};
use std::fs::File;
use std::io::{self, BufReader};
-use actix_web::{http::header::ContentType, web, App, HttpRequest, HttpResponse, HttpServer};
+use actix_web::{
+ dev::ServiceRequest, http::header::ContentType, web, App, HttpResponse, HttpServer,
+};
+use actix_web_httpauth::extractors::basic::{BasicAuth, Config};
+use actix_web_httpauth::extractors::AuthenticationError;
+use actix_web_httpauth::middleware::HttpAuthentication;
+use nix::sys::reboot::{reboot, RebootMode};
use rustls::{Certificate, PrivateKey, ServerConfig};
use rustls_pemfile::{certs, pkcs8_private_keys};
-async fn index(req: HttpRequest) -> HttpResponse {
- HttpResponse::Ok()
- .content_type(ContentType::plaintext())
- .body("it works")
+async fn handle_reboot() -> HttpResponse {
+ match reboot(RebootMode::RB_AUTOBOOT) {
+ Ok(_) => HttpResponse::Ok()
+ .content_type(ContentType::plaintext())
+ .body("rebooting..."),
+ Err(e) => HttpResponse::InternalServerError()
+ .content_type(ContentType::plaintext())
+ .body(format!("can't reboot: {}", e)),
+ }
+}
+
+async fn basic_auth_validator(
+ req: ServiceRequest,
+ credentials: BasicAuth,
+) -> std::result::Result<ServiceRequest, (actix_web::Error, ServiceRequest)> {
+ let config = req.app_data::<Config>().cloned().unwrap_or_default();
+
+ match validate_credentials(
+ credentials.user_id(),
+ credentials.password().unwrap_or_default().trim(),
+ ) {
+ Ok(res) => {
+ if res {
+ Ok(req)
+ } else {
+ Err((AuthenticationError::from(config).into(), req))
+ }
+ }
+ Err(_) => Err((AuthenticationError::from(config).into(), req)),
+ }
+}
+
+fn validate_credentials(user_id: &str, user_password: &str) -> io::Result<bool> {
+ if user_id == "rustkrazy" && user_password == "rustkrazy" {
+ return Ok(true);
+ }
+
+ Err(io::Error::new(
+ io::ErrorKind::PermissionDenied,
+ "Invalid credentials",
+ ))
}
#[actix_web::main]
@@ -31,12 +74,15 @@ async fn start() -> Result<()> {
println!("[admind] start https://[::]:8443");
- Ok(
- HttpServer::new(|| App::new().service(web::resource("/").to(index)))
- .bind_rustls("[::]:8443", config)?
- .run()
- .await?,
- )
+ Ok(HttpServer::new(|| {
+ let auth = HttpAuthentication::basic(basic_auth_validator);
+ App::new()
+ .wrap(auth)
+ .service(web::resource("/rustkrazy/reboot").to(handle_reboot))
+ })
+ .bind_rustls("[::]:8443", config)?
+ .run()
+ .await?)
}
fn load_rustls_config() -> Result<ServerConfig> {