feat: add nix dependency and enhance socket permissions handling
This commit is contained in:
@@ -18,12 +18,15 @@ use crate::routes::{status, validate, validate_and_reload, write_config};
|
||||
const SOCK_ARG: &str = "sock";
|
||||
const NGINX_CONFIG_DIR_ARG: &str = "nginx_config_dir";
|
||||
const SOCK_PERM_ARG: &str = "sock_perm";
|
||||
const SOCK_GID_ARG: &str = "sock_gid";
|
||||
const SOCK_ENV: &str = "YANPM_AGENT_SOCK";
|
||||
const SOCK_PERM_ENV: &str = "YANPM_AGENT_SOCK_PERM";
|
||||
const NGINX_CONFIG_DIR_ENV: &str = "YANPM_NGINX_CONFIG_DIR";
|
||||
const SOCK_GID_ENV: &str = "YANPM_AGENT_SOCK_GID";
|
||||
const SOCK_DEFAULT: &str = "./yanpm-agent.sock";
|
||||
const NGINX_CONFIG_DIR_DEFAULT: &str = "/etc/nginx/conf.d";
|
||||
const SOCK_PERM_DEFAULT: &str = "660";
|
||||
const SOCK_GID_DEFAULT: &str = "";
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
@@ -39,7 +42,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
|
||||
let args = Command::new("yanpm-agent")
|
||||
.arg(
|
||||
Arg::new("sock")
|
||||
Arg::new(SOCK_ARG)
|
||||
.short('s')
|
||||
.long("sock")
|
||||
.value_name("SOCK_PATH")
|
||||
@@ -47,7 +50,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("nginx_config_dir")
|
||||
Arg::new(NGINX_CONFIG_DIR_ARG)
|
||||
.short('d')
|
||||
.long("nginx-config-dir")
|
||||
.value_name("NGINX_CONFIG_DIR")
|
||||
@@ -55,16 +58,23 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("sock_perm")
|
||||
Arg::new(SOCK_PERM_ARG)
|
||||
.long("sock-perm")
|
||||
.value_name("SOCK_PERM")
|
||||
.help("Permissions to set on the unix socket (in octal), e.g. 660")
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(SOCK_GID_ARG)
|
||||
.long("sock-gid")
|
||||
.value_name("SOCK_GID")
|
||||
.help("GID to set on the unix socket, default: current user's primary group")
|
||||
.required(false),
|
||||
)
|
||||
.about("YANPM Agent Daemon")
|
||||
.get_matches();
|
||||
|
||||
let (sock, nginx_config_dir, sock_perm) = get_args(&args).await?;
|
||||
let (sock, nginx_config_dir, sock_perm, sock_gid) = get_args(&args).await?;
|
||||
|
||||
let path = PathBuf::from(&sock);
|
||||
if let Some(dir) = path.parent() {
|
||||
@@ -123,6 +133,27 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
);
|
||||
}
|
||||
|
||||
// set socket gid to sock_gid (best-effort)
|
||||
if !sock_gid.is_empty() {
|
||||
use nix::unistd::{Gid, chown};
|
||||
if let Err(err) = chown(
|
||||
&path,
|
||||
None,
|
||||
Some(Gid::from_raw(
|
||||
sock_gid
|
||||
.parse()
|
||||
.map_err(|e| format!("Failed to parse socket GID {}: {}", sock_gid, e))
|
||||
.unwrap_or_else(|_| nix::unistd::getgid().as_raw()),
|
||||
)),
|
||||
) {
|
||||
error!(
|
||||
"Warning: failed to set GID on socket {}: {}",
|
||||
path.display(),
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let scheduler = Arc::new(tokio_cron_scheduler::JobScheduler::new().await?);
|
||||
|
||||
let app = Router::new()
|
||||
@@ -145,7 +176,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
|
||||
async fn get_args(
|
||||
args: &clap::ArgMatches,
|
||||
) -> Result<(String, String, u32), Box<dyn std::error::Error + Send + Sync>> {
|
||||
) -> Result<(String, String, u32, String), Box<dyn std::error::Error + Send + Sync>> {
|
||||
let sock = args
|
||||
.get_one::<String>(SOCK_ARG)
|
||||
.cloned()
|
||||
@@ -164,6 +195,13 @@ async fn get_args(
|
||||
std::env::var(SOCK_PERM_ENV).unwrap_or_else(|_| SOCK_PERM_DEFAULT.to_string())
|
||||
});
|
||||
|
||||
let sock_gid = args
|
||||
.get_one::<String>(SOCK_GID_ARG)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| {
|
||||
std::env::var(SOCK_GID_ENV).unwrap_or_else(|_| SOCK_GID_DEFAULT.to_string())
|
||||
});
|
||||
|
||||
if sock_perm.len() != 3 || !sock_perm.chars().all(|c| ('0'..='7').contains(&c)) {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
@@ -177,8 +215,8 @@ async fn get_args(
|
||||
|
||||
if sock_perm.chars().last().unwrap() > '0' {
|
||||
warn!(
|
||||
"Socket permission string {} allows others to access the socket. This may be a security risk.",
|
||||
sock_perm
|
||||
"Socket permission string {} allows others to access the socket. This may be a security risk. Consider setting {} to a desired group and using a socket permission string that does not allow others to access the socket.",
|
||||
sock_perm, SOCK_GID_ENV
|
||||
);
|
||||
};
|
||||
|
||||
@@ -186,5 +224,6 @@ async fn get_args(
|
||||
sock,
|
||||
nginx_config_dir,
|
||||
u32::from_str_radix(&sock_perm, 8).expect("Failed to parse socket permission string"),
|
||||
sock_gid,
|
||||
))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user