aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Garrelou <simon.garrelou@gmail.com>2023-06-02 21:23:29 +0200
committerSimon Garrelou <simon.garrelou@gmail.com>2023-06-02 21:23:29 +0200
commitc0140aa3ace8e9d87f118c56d242a2afbea36d33 (patch)
tree8e9b1adb40ba7e71b36fd31437d7f26eaf633c9e
parent4e2bb828db4afa55c0cbcd4b5bce14ca64b982e3 (diff)
downloadwgmgr-c0140aa3ace8e9d87f118c56d242a2afbea36d33.tar.gz
wgmgr-c0140aa3ace8e9d87f118c56d242a2afbea36d33.zip
Put each function into its own file
-rw-r--r--src/add.rs33
-rw-r--r--src/config.rs16
-rw-r--r--src/configuration.rs31
-rw-r--r--src/list.rs14
-rw-r--r--src/main.rs143
-rw-r--r--src/rm.rs36
-rw-r--r--src/wgcmd.rs25
7 files changed, 157 insertions, 141 deletions
diff --git a/src/add.rs b/src/add.rs
new file mode 100644
index 0000000..8ccf53b
--- /dev/null
+++ b/src/add.rs
@@ -0,0 +1,33 @@
1use std::{net::Ipv4Addr, str::FromStr, fs::File};
2use std::io::Write;
3use anyhow::{anyhow, Result};
4use crate::wg::{config::WireguardConfig, peer::Peer};
5
6pub fn run(wg_conf: &mut WireguardConfig, wg_conf_path: String, peer_name: &String, ip: Option<&String>) -> Result<()> {
7 let ip = match ip {
8 Some(s) => {
9 Ipv4Addr::from_str(s.as_str())?
10 },
11 None => {
12 match wg_conf.next_free_ip() {
13 Ok(i) => i,
14 Err(e) => {
15 return Err(e);
16 }
17 }
18 }
19 };
20
21 match wg_conf.get_peer(peer_name.as_str()) {
22 Some(_) => { return Err(anyhow!("There is already a peer named {}", peer_name)); },
23 None => {}
24 }
25
26 let p = Peer::new(peer_name.clone(), ip)?;
27 wg_conf.peers.push(p);
28
29 let mut f = File::create(wg_conf_path)?;
30 write!(f, "{}", wg_conf.gen_config()?)?;
31
32 Ok(())
33} \ No newline at end of file
diff --git a/src/config.rs b/src/config.rs
new file mode 100644
index 0000000..5ae4e1e
--- /dev/null
+++ b/src/config.rs
@@ -0,0 +1,16 @@
1use crate::wg::config::WireguardConfig;
2use crate::Configuration;
3use anyhow::{anyhow, Result};
4
5pub fn run(wg_conf: &WireguardConfig, conf: &Configuration, peer_name: String, is_full: bool) -> Result<()> {
6 let peer = match wg_conf.get_peer(peer_name.as_str()) {
7 Some(p) => p,
8 None => {
9 return Err(anyhow!("No such peer: {}", peer_name));
10 }
11 };
12
13 println!("{}", peer.gen_config(wg_conf, conf.dns.clone(), conf.endpoint.clone(), conf.port, is_full)?);
14
15 Ok(())
16} \ No newline at end of file
diff --git a/src/configuration.rs b/src/configuration.rs
deleted file mode 100644
index 839db24..0000000
--- a/src/configuration.rs
+++ /dev/null
@@ -1,31 +0,0 @@
1use serde::Deserialize;
2use anyhow::{Result, anyhow, Context};
3use std::fs::read_to_string;
4
5#[derive(Deserialize)]
6pub struct Configuration {
7 pub endpoint: String,
8 pub wgconf: String,
9 pub port: Option<u32>,
10 pub dns: Option<String>,
11}
12
13pub fn find_configuration_file(argument: Option<&String>) -> Result<Configuration> {
14 match argument {
15 Some(p) => {
16 if let Ok(t) = read_to_string(p) {
17 let c: Configuration = toml::from_str(&t).context("parsing configuration file")?;
18 return Ok(c)
19 }
20 },
21 None => {
22 // Try /etc/wgmgr.toml
23 if let Ok(t) = read_to_string("/etc/wgmgr.toml") {
24 let c: Configuration = toml::from_str(&t).context("parsing /etc/wgmgr.toml")?;
25 return Ok(c)
26 }
27 },
28 };
29
30 Err(anyhow!("Could not find a valid configuration file for wgmgr."))
31}
diff --git a/src/list.rs b/src/list.rs
new file mode 100644
index 0000000..3baba8f
--- /dev/null
+++ b/src/list.rs
@@ -0,0 +1,14 @@
1use crate::wg::config::WireguardConfig;
2
3pub fn run(wg_conf: &WireguardConfig) {
4 let mut max_length = 0;
5 for p in wg_conf.peers.iter() {
6 if p.name.len() > max_length {
7 max_length = p.name.len();
8 }
9 }
10
11 for p in wg_conf.peers.iter() {
12 println!("{:max_length$} | {}", p.name, p.ip);
13 }
14} \ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 3f82d43..17b920d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,16 +1,17 @@
1use std::fs::File;
2use std::net::Ipv4Addr;
3use std::str::FromStr;
4use std::{env, process::exit}; 1use std::{env, process::exit};
5use std::io::Write; 2
6use std::process::Command as processCommand;
7 3
8use anyhow::{Result, anyhow, Context}; 4use anyhow::{Result, anyhow, Context};
9use clap::{arg, command, Command}; 5use clap::{arg, command, Command};
10use wg::config::WireguardConfig; 6use serde::Deserialize;
7use std::fs::read_to_string;
11 8
12mod wg; 9mod wg;
13mod configuration; 10mod list;
11mod rm;
12mod add;
13mod wgcmd;
14mod config;
14 15
15fn main() { 16fn main() {
16 let matches = command!() 17 let matches = command!()
@@ -80,7 +81,7 @@ fn main() {
80 81
81 82
82 // Find the configuration file for wgmgr 83 // Find the configuration file for wgmgr
83 let wgmgr_conf = match configuration::find_configuration_file(matches.get_one::<String>("config")) { 84 let wgmgr_conf = match find_configuration_file(matches.get_one::<String>("config")) {
84 Ok(c) => c, 85 Ok(c) => c,
85 Err(e) => { 86 Err(e) => {
86 eprintln!("Could not find wgmgr configuration file. Place it at /etc/wgmgr.toml or use the --config flag."); 87 eprintln!("Could not find wgmgr configuration file. Place it at /etc/wgmgr.toml or use the --config flag.");
@@ -102,7 +103,7 @@ fn main() {
102 103
103 match matches.subcommand() { 104 match matches.subcommand() {
104 Some(("ls", _)) => { 105 Some(("ls", _)) => {
105 do_list(&wg_conf); 106 list::run(&wg_conf);
106 } 107 }
107 108
108 Some(("config", args)) => { 109 Some(("config", args)) => {
@@ -122,7 +123,7 @@ fn main() {
122 None => false 123 None => false
123 }; 124 };
124 125
125 if let Err(e) = do_config(&wg_conf, &wgmgr_conf, peer_name.to_string(), is_full) { 126 if let Err(e) = config::run(&wg_conf, &wgmgr_conf, peer_name.to_string(), is_full) {
126 eprintln!("Error generating configuration for {}: {:?}", peer_name.to_string(), e); 127 eprintln!("Error generating configuration for {}: {:?}", peer_name.to_string(), e);
127 exit(1); 128 exit(1);
128 } 129 }
@@ -133,7 +134,7 @@ fn main() {
133 134
134 Some(("add", args)) => { 135 Some(("add", args)) => {
135 let new_name = args.get_one::<String>("NAME").unwrap().to_string(); 136 let new_name = args.get_one::<String>("NAME").unwrap().to_string();
136 if let Err(e) = do_add(&mut wg_conf, wgmgr_conf.wgconf, &new_name, args.get_one::<String>("ip")) { 137 if let Err(e) = add::run(&mut wg_conf, wgmgr_conf.wgconf, &new_name, args.get_one::<String>("ip")) {
137 eprintln!("Error adding peer: {:?}", e); 138 eprintln!("Error adding peer: {:?}", e);
138 exit(1); 139 exit(1);
139 } 140 }
@@ -144,7 +145,7 @@ fn main() {
144 145
145 Some(("rm", args)) => { 146 Some(("rm", args)) => {
146 let rm_name = args.get_one::<String>("NAME").unwrap().to_string(); 147 let rm_name = args.get_one::<String>("NAME").unwrap().to_string();
147 if let Err(e) = do_rm(&mut wg_conf, wgmgr_conf.wgconf, &rm_name) { 148 if let Err(e) = rm::run(&mut wg_conf, wgmgr_conf.wgconf, &rm_name) {
148 eprintln!("Error removing peer: {:?}", e); 149 eprintln!("Error removing peer: {:?}", e);
149 exit(1); 150 exit(1);
150 } 151 }
@@ -153,7 +154,7 @@ fn main() {
153 }, 154 },
154 155
155 Some(("wg", _)) => { 156 Some(("wg", _)) => {
156 if let Err(e) = do_wg(&wg_conf) { 157 if let Err(e) = wgcmd::run(&wg_conf) {
157 eprintln!("{:?}", e); 158 eprintln!("{:?}", e);
158 exit(1); 159 exit(1);
159 } 160 }
@@ -166,109 +167,31 @@ fn main() {
166 167
167} 168}
168 169
169fn do_list(wg_conf: &wg::config::WireguardConfig) { 170#[derive(Deserialize)]
170 let mut max_length = 0; 171pub struct Configuration {
171 for p in wg_conf.peers.iter() { 172 pub endpoint: String,
172 if p.name.len() > max_length { 173 pub wgconf: String,
173 max_length = p.name.len(); 174 pub port: Option<u32>,
174 } 175 pub dns: Option<String>,
175 }
176
177 for p in wg_conf.peers.iter() {
178 println!("{:max_length$} | {}", p.name, p.ip);
179 }
180} 176}
181 177
182fn do_config(wg_conf: &wg::config::WireguardConfig, conf: &configuration::Configuration, peer_name: String, is_full: bool) -> Result<()> { 178pub fn find_configuration_file(argument: Option<&String>) -> Result<Configuration> {
183 let peer = match wg_conf.get_peer(peer_name.as_str()) { 179 match argument {
184 Some(p) => p, 180 Some(p) => {
185 None => { 181 if let Ok(t) = read_to_string(p) {
186 return Err(anyhow!("No such peer: {}", peer_name)); 182 let c: Configuration = toml::from_str(&t).context("parsing configuration file")?;
187 } 183 return Ok(c)
188 }; 184 }
189
190 println!("{}", peer.gen_config(wg_conf, conf.dns.clone(), conf.endpoint.clone(), conf.port, is_full)?);
191
192 Ok(())
193}
194
195fn do_add(wg_conf: &mut WireguardConfig, wg_conf_path: String, peer_name: &String, ip: Option<&String>) -> Result<()> {
196 let ip = match ip {
197 Some(s) => {
198 Ipv4Addr::from_str(s.as_str())?
199 }, 185 },
200 None => { 186 None => {
201 match wg_conf.next_free_ip() { 187 // Try /etc/wgmgr.toml
202 Ok(i) => i, 188 if let Ok(t) = read_to_string("/etc/wgmgr.toml") {
203 Err(e) => { 189 let c: Configuration = toml::from_str(&t).context("parsing /etc/wgmgr.toml")?;
204 return Err(e); 190 return Ok(c)
205 }
206 } 191 }
207 } 192 },
208 }; 193 };
209 194
210 match wg_conf.get_peer(peer_name.as_str()) { 195 Err(anyhow!("Could not find a valid configuration file for wgmgr."))
211 Some(_) => { return Err(anyhow!("There is already a peer named {}", peer_name)); },
212 None => {}
213 }
214
215 let p = wg::peer::Peer::new(peer_name.clone(), ip)?;
216 wg_conf.peers.push(p);
217
218 let mut f = File::create(wg_conf_path)?;
219 write!(f, "{}", wg_conf.gen_config()?)?;
220
221 Ok(())
222} 196}
223 197
224fn do_rm(wg_conf: &mut WireguardConfig, wg_conf_path: String, peer_name: &String) -> Result<()> {
225 let mut del_index = 0;
226 let mut found = false;
227 let mut pk_path = String::new();
228
229 for (i, peer) in wg_conf.peers.iter().enumerate() {
230 if &peer.name == peer_name {
231 del_index = i;
232 found = true;
233 pk_path = peer.private_key_path().context("could not get private key path")?;
234 break;
235 }
236 }
237
238 if !found {
239 return Err(anyhow!("No such peer: {}", peer_name));
240 }
241
242 wg_conf.peers.remove(del_index);
243
244 let mut f = File::create(wg_conf_path.clone()).context(format!("error opening configuration file: {}", wg_conf_path))?;
245 let data = wg_conf.gen_config().context("error generating configuration")?;
246
247 f.write_all(data.as_bytes()).context(format!("error writing to file: {}", wg_conf_path))?;
248
249 std::fs::remove_file(pk_path).context(format!("could not remove file: {}", wg_conf_path))?;
250
251 Ok(())
252}
253
254fn do_wg(wg_conf: &WireguardConfig) -> Result<()> {
255 let wg = processCommand::new("wg")
256 .env("WG_COLOR_MODE", "always")
257 .output()
258 .context("could not run 'wg', is it installed?")?;
259
260 if !wg.status.success() {
261 let err = String::from_utf8(wg.stderr)?;
262 return Err(anyhow!("error running 'wg': {}", err));
263 }
264
265 let mut out = String::from_utf8(wg.stdout).context("error parsing stdout")?;
266
267 for peer in wg_conf.peers.iter() {
268 out = out.replace(peer.public_key.as_str(), peer.name.as_str());
269 }
270
271 println!("{}", out);
272
273 Ok(())
274}
diff --git a/src/rm.rs b/src/rm.rs
new file mode 100644
index 0000000..61880d2
--- /dev/null
+++ b/src/rm.rs
@@ -0,0 +1,36 @@
1use std::{fs::File, io::Write};
2
3use anyhow::{anyhow, Result, Context};
4
5use crate::wg::config::WireguardConfig;
6
7pub fn run(wg_conf: &mut WireguardConfig, wg_conf_path: String, peer_name: &String) -> Result<()> {
8 let mut del_index = 0;
9 let mut found = false;
10 let mut pk_path = String::new();
11
12 for (i, peer) in wg_conf.peers.iter().enumerate() {
13 if &peer.name == peer_name {
14 del_index = i;
15 found = true;
16 pk_path = peer.private_key_path().context("could not get private key path")?;
17 break;
18 }
19 }
20
21 if !found {
22 return Err(anyhow!("No such peer: {}", peer_name));
23 }
24
25 wg_conf.peers.remove(del_index);
26
27 let mut f = File::create(wg_conf_path.clone()).context(format!("error opening configuration file: {}", wg_conf_path))?;
28 let data = wg_conf.gen_config().context("error generating configuration")?;
29
30 f.write_all(data.as_bytes()).context(format!("error writing to file: {}", wg_conf_path))?;
31
32 std::fs::remove_file(pk_path).context(format!("could not remove file: {}", wg_conf_path))?;
33
34 Ok(())
35}
36
diff --git a/src/wgcmd.rs b/src/wgcmd.rs
new file mode 100644
index 0000000..32a23a6
--- /dev/null
+++ b/src/wgcmd.rs
@@ -0,0 +1,25 @@
1use crate::wg::config::WireguardConfig;
2use std::process::Command;
3use anyhow::{anyhow, Result, Context};
4
5pub fn run(wg_conf: &WireguardConfig) -> Result<()> {
6 let wg = Command::new("wg")
7 .env("WG_COLOR_MODE", "always")
8 .output()
9 .context("could not run 'wg', is it installed?")?;
10
11 if !wg.status.success() {
12 let err = String::from_utf8(wg.stderr)?;
13 return Err(anyhow!("error running 'wg': {}", err));
14 }
15
16 let mut out = String::from_utf8(wg.stdout).context("error parsing stdout")?;
17
18 for peer in wg_conf.peers.iter() {
19 out = out.replace(peer.public_key.as_str(), peer.name.as_str());
20 }
21
22 println!("{}", out);
23
24 Ok(())
25}