Initial commit
This commit is contained in:
commit
030bbcc100
3 changed files with 389 additions and 0 deletions
116
Cargo.lock
generated
Executable file
116
Cargo.lock
generated
Executable file
|
@ -0,0 +1,116 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"lazy_static",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
|
||||
|
||||
[[package]]
|
||||
name = "maniver"
|
||||
version = "0.1.0-dev"
|
||||
dependencies = [
|
||||
"colored",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"thread_local",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb9bc092d0d51e76b2b19d9d85534ffc9ec2db959a2523cdae0697e2972cd447"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
11
Cargo.toml
Executable file
11
Cargo.toml
Executable file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "maniver"
|
||||
version = "0.1.0-dev"
|
||||
authors = ["Miraty <miraty@antopie.org>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
regex = "1"
|
||||
colored = "2"
|
262
src/main.rs
Executable file
262
src/main.rs
Executable file
|
@ -0,0 +1,262 @@
|
|||
use std::env;
|
||||
use regex::Regex;
|
||||
use std::io::prelude::*;
|
||||
use std::process::{Command, Stdio};
|
||||
use colored::*;
|
||||
use std::fs;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let tool = args[1].to_string();
|
||||
match tool.as_ref() {
|
||||
"setup-user" => setup_user(args[2].to_string(), args[3].to_string()),
|
||||
"reload-nginx" => reload_nginx(),
|
||||
"reload-tor" => reload_tor(),
|
||||
"le-install" => le_install(args[2].to_string()),
|
||||
"export-tor" => export_tor(args[2].to_string(), args[3].to_string()),
|
||||
_ => println!("{}{}{}{}\n{}{}{}{}{}{}{}{}{}", "maniver : ", "ERREUR : ".red(), tool.red(), " : argument non reconnu".red(), " > Utilisez ", "setup-user <user> <password>".italic().green(), ", ", "reload-nginx".italic().green(), ", ", "reload-tor".italic().green(), " ou ", "le-install <domaine>".italic().green(), " comme argument"),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn export_tor(username: String, dir: String) {
|
||||
|
||||
let mut src_path: String = "/var/lib/tor/niver/".to_owned();
|
||||
src_path += &dir.to_string();
|
||||
src_path += &"/hostname".to_string().to_owned();
|
||||
|
||||
let mut dest_path: String = "/srv/hyper/".to_owned();
|
||||
dest_path += &username.to_string();
|
||||
dest_path += &"/hyper/".to_string().to_owned();
|
||||
dest_path += &dir.to_string();
|
||||
dest_path += &"/hostname".to_string().to_owned();
|
||||
|
||||
match fs::copy(src_path, &dest_path) {
|
||||
Err(why) => panic!("Erreur lors d'une copie de fichier (fs::copy) : {}", why),
|
||||
Ok(process) => process,
|
||||
};
|
||||
|
||||
let output = Command::new("/usr/bin/chown")
|
||||
.arg("www-data:www-data")
|
||||
.arg(dest_path)
|
||||
.output()
|
||||
.expect("failed to execute process");
|
||||
|
||||
println!("status: {}", output.status);
|
||||
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||
assert!(output.status.success());
|
||||
|
||||
//let output = Command::new("/usr/bin/cp")
|
||||
// .arg(src_path)
|
||||
// .arg(dest_path)
|
||||
// .output()
|
||||
// .expect("failed to execute process");
|
||||
|
||||
//println!("status: {}", output.status);
|
||||
//println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
//println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||
//assert!(output.status.success());
|
||||
|
||||
}
|
||||
|
||||
fn le_install(domain: String) {
|
||||
|
||||
let output = Command::new("/usr/bin/certbot")
|
||||
.arg("--nginx")
|
||||
.arg("-d")
|
||||
.arg(&domain)
|
||||
.output()
|
||||
.expect("failed to execute process");
|
||||
|
||||
println!("status: {}", output.status);
|
||||
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||
|
||||
assert!(output.status.success());
|
||||
|
||||
}
|
||||
|
||||
fn reload_nginx() {
|
||||
|
||||
let output = Command::new("/usr/bin/systemctl")
|
||||
.arg("reload")
|
||||
.arg("nginx")
|
||||
.output()
|
||||
.expect("Error while reloading Nginx config");
|
||||
|
||||
println!("status: {}", output.status);
|
||||
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||
|
||||
assert!(output.status.success());
|
||||
}
|
||||
|
||||
fn reload_tor() {
|
||||
|
||||
Command::new("/usr/bin/systemctl")
|
||||
.arg("reload")
|
||||
.arg("tor@default")
|
||||
.output()
|
||||
.expect("Error while reloading Tor config");
|
||||
|
||||
//let output = Command::new("/usr/bin/chown")
|
||||
// .arg("-R")
|
||||
// .arg("www-data:www-data")
|
||||
// .arg("/var/lib/tor/niver")
|
||||
// .output()
|
||||
// .expect("failed to execute process");
|
||||
|
||||
//println!("status: {}", output.status);
|
||||
//println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
//println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||
//assert!(output.status.success());
|
||||
|
||||
}
|
||||
|
||||
fn setup_user(username: String, password: String) {
|
||||
|
||||
if username.chars().count() < 32 {
|
||||
if password.chars().count() < 1024 {
|
||||
if is_string_lowercase(username.to_string()) {
|
||||
|
||||
let username1 = &username;
|
||||
let username2 = &username;
|
||||
let username3 = &username;
|
||||
let username4 = &username;
|
||||
newser(username1.to_string());
|
||||
pwd(username2.to_string(), password);
|
||||
chroot(username3.to_string());
|
||||
quota(username4.to_string());
|
||||
|
||||
} else {
|
||||
println!("Erreur : l'username doit être composé de lettres minuscules uniquement");
|
||||
}
|
||||
} else {
|
||||
println!("Erreur : le mot de passe doit faire moins de 1024 caractères");
|
||||
}
|
||||
} else {
|
||||
println!("Erreur : l'username doit faire moins de 32 caractères");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Set disk usage limit to the user by copying another user quota
|
||||
fn quota(username: String) {
|
||||
|
||||
let output = Command::new("/usr/sbin/edquota")
|
||||
.arg("-p")
|
||||
.arg("testfract")
|
||||
.arg(&username)
|
||||
.output()
|
||||
.expect("failed to execute process");
|
||||
|
||||
println!("status: {}", output.status);
|
||||
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||
|
||||
assert!(output.status.success());
|
||||
|
||||
}
|
||||
|
||||
// Chown /srv/hyper/username to root:root
|
||||
fn chroot(username: String) {
|
||||
|
||||
if username.chars().count() < 32 {
|
||||
|
||||
let mut path = "/srv/hyper/".to_string();
|
||||
|
||||
path += &username;
|
||||
|
||||
let output = Command::new("/usr/bin/chown")
|
||||
.arg("root:root")
|
||||
.arg(&path)
|
||||
.output()
|
||||
.expect("Failed to chown /srv/hyper/<username> to root:root");
|
||||
|
||||
println!("status: {}", output.status);
|
||||
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||
assert!(output.status.success());
|
||||
|
||||
let output = Command::new("/usr/bin/chmod")
|
||||
.arg("755")
|
||||
.arg(path)
|
||||
.output()
|
||||
.expect("Failed to chmod /srv/hyper/<username> to 755");
|
||||
|
||||
println!("status: {}", output.status);
|
||||
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||
assert!(output.status.success());
|
||||
|
||||
} else {
|
||||
println!("Erreur : l'username doit faire moins de 32 caractères");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Creates a new user in the group 'hyper', which is available only over SFTP
|
||||
fn newser(username: String) {
|
||||
|
||||
let output = Command::new("/usr/sbin/useradd")
|
||||
.arg(&username)
|
||||
.arg("--create-home")
|
||||
.arg("--base-dir")
|
||||
.arg("/srv/hyper")
|
||||
.arg("--gid")
|
||||
.arg("hyper")
|
||||
.arg("--shell")
|
||||
.arg("/usr/sbin/nologin")
|
||||
.output()
|
||||
.expect("failed to execute process");
|
||||
|
||||
println!("status: {}", output.status);
|
||||
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||
|
||||
assert!(output.status.success());
|
||||
|
||||
}
|
||||
|
||||
// Changes password of the newly created user
|
||||
fn pwd(username: String, password: String) {
|
||||
|
||||
// line must be in the form username:password
|
||||
let mut line: String = username.to_string();
|
||||
line += &":".to_string().to_owned();
|
||||
line += &password.to_owned();
|
||||
|
||||
let process = match Command::new("/usr/sbin/chpasswd")
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn() {
|
||||
Err(why) => panic!("couldn't spawn chpasswd: {}", why),
|
||||
Ok(process) => process,
|
||||
};
|
||||
|
||||
match process.stdin.unwrap().write_all(line.as_bytes()) {
|
||||
Err(why) => panic!("couldn't write to chpasswd stdin: {}", why),
|
||||
Ok(_) => println!("sent username:password to chpasswd"),
|
||||
}
|
||||
|
||||
let mut s = String::new();
|
||||
match process.stdout.unwrap().read_to_string(&mut s) {
|
||||
Err(why) => panic!("couldn't read chpasswd stdout: {}", why),
|
||||
Ok(_) => print!("chpasswd responded with:\n{}", s),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn is_string_lowercase(stri: String) -> bool {
|
||||
|
||||
let re = Regex::new("^[[:lower:]]+$").unwrap();
|
||||
let matching = re.is_match(&stri);
|
||||
if matching {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue