feat: Implement SSH Agent Connector and gRPC server
- Added `AgentConnectorTrait` and `AgentConnector` for managing agent connections. - Introduced `SshAgentConnector` to handle SSH-related functionalities and start a gRPC server. - Created database entities for `agents`, `certificates`, `organizations`, `public_key_revocations`, `setup_tokens`, `upstreams`, `users`, `virtual_hosts`, and `workspaces` using SeaORM. - Developed `CertificateService` for managing certificate generation and retrieval. - Implemented the main server logic to initialize the database connection and start the agent server. - Configured development settings in `development.toml` for server and database connections.
This commit is contained in:
52
apps/nxmesh-master/src/cli/gen_agent_certs.rs
Normal file
52
apps/nxmesh-master/src/cli/gen_agent_certs.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use tracing::{error, info};
|
||||
|
||||
use crate::{config::settings::Settings, db, service};
|
||||
|
||||
pub async fn gen_agent_certs(
|
||||
settings: &Settings,
|
||||
output: String,
|
||||
agent_id: String,
|
||||
zip: bool,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
info!("Generating certificates to output directory: {}", output);
|
||||
use service::certificate::CertificateService;
|
||||
//
|
||||
let cert_service = service::certificate::CertificateServiceImpl::new(
|
||||
#[expect(clippy::expect_used)]
|
||||
db::establish_connection(&settings.database.url)
|
||||
.await
|
||||
.expect("Failed to connect to database"),
|
||||
output.clone(),
|
||||
Arc::new(settings.clone()),
|
||||
);
|
||||
|
||||
let output = cert_service
|
||||
.generate_agent_certs(&agent_id, &output)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Failed to generate agent certificates: {}", e);
|
||||
std::process::exit(1);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
info!(
|
||||
"Successfully generated agent certificates at: cert path: {}, key path: {}, ca cert path: {}",
|
||||
output.cert_path, output.key_path, output.ca_cert_path
|
||||
);
|
||||
if zip {
|
||||
// Implementation for zipping certificates
|
||||
info!("Zipping generated certificates...");
|
||||
if let Err(e) = cert_service
|
||||
.zip_certificates(&output.cert_path, &output.key_path, &output.ca_cert_path)
|
||||
.await
|
||||
{
|
||||
error!("Failed to zip certificates: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
info!("Successfully zipped certificates.");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
31
apps/nxmesh-master/src/cli/gen_certs.rs
Normal file
31
apps/nxmesh-master/src/cli/gen_certs.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use tracing::{error, info};
|
||||
|
||||
use crate::{config::settings::Settings, db, service};
|
||||
|
||||
pub async fn gen_certs(
|
||||
settings: &Settings,
|
||||
output: String,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
info!("Generating CA certificate to output directory: {}", output);
|
||||
use service::certificate::CertificateService;
|
||||
let cert_service = service::certificate::CertificateServiceImpl::new(
|
||||
#[expect(clippy::expect_used)]
|
||||
db::establish_connection(&settings.database.url)
|
||||
.await
|
||||
.expect("Failed to connect to database"),
|
||||
output.to_string(),
|
||||
Arc::new(settings.clone()),
|
||||
);
|
||||
cert_service
|
||||
.generate_ca_cert()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Failed to generate CA certificate: {}", e);
|
||||
std::process::exit(1);
|
||||
})
|
||||
.unwrap();
|
||||
info!("Successfully generated CA certificate at: {}", output);
|
||||
Ok(())
|
||||
}
|
||||
63
apps/nxmesh-master/src/cli/mod.rs
Normal file
63
apps/nxmesh-master/src/cli/mod.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
mod gen_agent_certs;
|
||||
mod gen_certs;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
use crate::{
|
||||
cli::{gen_agent_certs::gen_agent_certs, gen_certs::gen_certs},
|
||||
config::settings::Settings,
|
||||
};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(version, about, long_about = None)]
|
||||
pub struct Cli {
|
||||
/// Start the master server
|
||||
#[arg(short, long, group = "mode")]
|
||||
pub serve: bool,
|
||||
|
||||
/// generate CA for key signing if not exist
|
||||
/// If the CA already exists, generating CA will be skipped and the existing CA will be used
|
||||
/// If the CA does not exist, a new CA will be generated and saved to the default location (./certs/ca.crt and ./certs/ca.key)
|
||||
/// The generated CA will be used for signing agent certificates
|
||||
/// If not specified, the server will check if the CA already exists and use it if available, otherwise exit with an error
|
||||
#[arg(long)]
|
||||
pub generate_ca: bool,
|
||||
|
||||
#[command(subcommand)]
|
||||
pub command: Option<Commands>,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
pub enum Commands {
|
||||
GenCerts {
|
||||
/// Output directory for generated certificates
|
||||
#[arg(short, long, default_value = "./certs")]
|
||||
output: String,
|
||||
},
|
||||
/// Generate certificates for agent
|
||||
#[command(about = "Generate certificates for agent")]
|
||||
GenAgentCerts {
|
||||
/// Output directory for generated certificates
|
||||
#[arg(short, long, default_value = "./certs")]
|
||||
output: String,
|
||||
#[arg(long, default_value = "agent-id-placeholder")]
|
||||
agent_id: String,
|
||||
#[arg(short, long, default_value = "false")]
|
||||
zip: bool,
|
||||
},
|
||||
}
|
||||
|
||||
pub async fn handle_sub_command(
|
||||
settings: &Settings,
|
||||
command: Commands,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
// run as a CLI tool for other commands
|
||||
match command {
|
||||
Commands::GenCerts { output } => Ok(gen_certs(settings, output).await?),
|
||||
Commands::GenAgentCerts {
|
||||
output,
|
||||
agent_id,
|
||||
zip,
|
||||
} => Ok(gen_agent_certs(settings, output, agent_id, zip).await?),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user