Merge pull request #44 from freeflowuniverse/development_wg
Add SAL for wireguard
This commit is contained in:
8
examples/develop/wireguard/wg0.conf
Normal file
8
examples/develop/wireguard/wg0.conf
Normal file
@@ -0,0 +1,8 @@
|
||||
[Interface]
|
||||
Address = 10.10.3.0/24
|
||||
PrivateKey = wDewSiri8jlaGnUDN6SwK7QhN082U7gfX27YMGILvVA=
|
||||
[Peer]
|
||||
PublicKey = 2JEGJQ8FbajdFk0fFs/881H/D3FRjwlUxvNDZFxDeWQ=
|
||||
AllowedIPs = 10.10.0.0/16, 100.64.0.0/16
|
||||
PersistentKeepalive = 25
|
||||
Endpoint = 185.206.122.31:3241
|
||||
35
examples/develop/wireguard/wireguard.vsh
Executable file
35
examples/develop/wireguard/wireguard.vsh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -no-retry-compilation -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.clients.wireguard
|
||||
import freeflowuniverse.herolib.installers.net.wireguard as wireguard_installer
|
||||
import time
|
||||
import os
|
||||
|
||||
mut wg_installer := wireguard_installer.get()!
|
||||
wg_installer.install()!
|
||||
|
||||
// Create Wireguard client
|
||||
mut wg := wireguard.get()!
|
||||
config_file_path := '${os.dir(@FILE)}/wg0.conf'
|
||||
|
||||
wg.start(config_file_path: config_file_path)!
|
||||
println('${config_file_path} is started')
|
||||
|
||||
time.sleep(time.second * 2)
|
||||
|
||||
info := wg.show()!
|
||||
println('info: ${info}')
|
||||
|
||||
config := wg.show_config(interface_name: 'wg0')!
|
||||
println('config: ${config}')
|
||||
|
||||
private_key := wg.generate_private_key()!
|
||||
println('private_key: ${private_key}')
|
||||
|
||||
public_key := wg.get_public_key(private_key: private_key)!
|
||||
println('public_key: ${public_key}')
|
||||
|
||||
wg.down(config_file_path: config_file_path)!
|
||||
println('${config_file_path} is down')
|
||||
|
||||
wg_installer.destroy()!
|
||||
8
lib/clients/wireguard/.heroscript
Normal file
8
lib/clients/wireguard/.heroscript
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
!!hero_code.generate_client
|
||||
name:'wireguard'
|
||||
classname:'WireGuard'
|
||||
singleton:0
|
||||
default:1
|
||||
hasconfig:1
|
||||
reset:0
|
||||
114
lib/clients/wireguard/client.v
Normal file
114
lib/clients/wireguard/client.v
Normal file
@@ -0,0 +1,114 @@
|
||||
module wireguard
|
||||
|
||||
import os
|
||||
|
||||
pub struct WGPeer {
|
||||
pub mut:
|
||||
endpoint string
|
||||
allowed_ips string
|
||||
latest_handshake string
|
||||
transfer string
|
||||
persistent_keepalive string
|
||||
}
|
||||
|
||||
pub struct WGInterface {
|
||||
pub mut:
|
||||
name string
|
||||
public_key string
|
||||
listening_port int
|
||||
}
|
||||
|
||||
pub struct WGInfo {
|
||||
pub mut:
|
||||
interface_ WGInterface
|
||||
peers map[string]WGPeer
|
||||
}
|
||||
|
||||
pub struct WGShow {
|
||||
pub mut:
|
||||
configs map[string]WGInfo
|
||||
}
|
||||
|
||||
pub fn (wg WireGuard) show() !WGShow {
|
||||
cmd := 'sudo wg show'
|
||||
res := os.execute(cmd)
|
||||
if res.exit_code != 0 {
|
||||
return error('failed to execute show command due to: ${res.output}')
|
||||
}
|
||||
|
||||
return wg.parse_show_command_output(res.output)
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ShowConfigArgs {
|
||||
pub:
|
||||
interface_name string @[required]
|
||||
}
|
||||
|
||||
pub fn (wg WireGuard) show_config(args ShowConfigArgs) !WGInfo {
|
||||
configs := wg.show()!.configs
|
||||
config := configs[args.interface_name] or {
|
||||
return error('key ${args.interface_name} does not exists.')
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct StartArgs {
|
||||
pub:
|
||||
config_file_path string @[required]
|
||||
}
|
||||
|
||||
pub fn (wg WireGuard) start(args StartArgs) ! {
|
||||
if !os.exists(args.config_file_path) {
|
||||
return error('File ${args.config_file_path} does not exists.')
|
||||
}
|
||||
|
||||
cmd := 'sudo wg-quick up ${args.config_file_path}'
|
||||
res := os.execute(cmd)
|
||||
if res.exit_code != 0 {
|
||||
return error('failed to execute start command due to: ${res.output}')
|
||||
}
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct DownArgs {
|
||||
pub:
|
||||
config_file_path string @[required]
|
||||
}
|
||||
|
||||
pub fn (wg WireGuard) down(args DownArgs) ! {
|
||||
if !os.exists(args.config_file_path) {
|
||||
return error('File ${args.config_file_path} does not exists.')
|
||||
}
|
||||
|
||||
cmd := 'sudo wg-quick down ${args.config_file_path}'
|
||||
res := os.execute(cmd)
|
||||
if res.exit_code != 0 {
|
||||
return error('failed to execute down command due to: ${res.output}')
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (wg WireGuard) generate_private_key() !string {
|
||||
cmd := 'wg genkey'
|
||||
res := os.execute(cmd)
|
||||
if res.exit_code != 0 {
|
||||
return error('failed to execute genkey command due to: ${res.output}')
|
||||
}
|
||||
return res.output.trim_space()
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct GetPublicKeyArgs {
|
||||
pub:
|
||||
private_key string @[required]
|
||||
}
|
||||
|
||||
pub fn (wg WireGuard) get_public_key(args GetPublicKeyArgs) !string {
|
||||
cmd := 'echo ${args.private_key} | wg pubkey'
|
||||
res := os.execute(cmd)
|
||||
if res.exit_code != 0 {
|
||||
return error('failed to execute pubkey command due to: ${res.output}')
|
||||
}
|
||||
return res.output.trim_space()
|
||||
}
|
||||
30
lib/clients/wireguard/readme.md
Normal file
30
lib/clients/wireguard/readme.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# wireguard
|
||||
|
||||
|
||||
|
||||
To get started
|
||||
|
||||
```vlang
|
||||
|
||||
|
||||
import freeflowuniverse.herolib.clients. wireguard
|
||||
|
||||
mut client:= wireguard.get()!
|
||||
|
||||
client...
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
## example heroscript
|
||||
|
||||
```hero
|
||||
!!wireguard.configure
|
||||
secret: '...'
|
||||
host: 'localhost'
|
||||
port: 8888
|
||||
```
|
||||
|
||||
|
||||
72
lib/clients/wireguard/utils.v
Normal file
72
lib/clients/wireguard/utils.v
Normal file
@@ -0,0 +1,72 @@
|
||||
module wireguard
|
||||
|
||||
fn (wg WireGuard) parse_show_command_output(res string) !WGShow {
|
||||
mut configs := map[string]WGInfo{}
|
||||
mut lines := res.split('\n')
|
||||
mut current_interface := ''
|
||||
mut current_peers := map[string]WGPeer{}
|
||||
mut iface := WGInterface{}
|
||||
mut peer_key := ''
|
||||
|
||||
for line in lines {
|
||||
mut parts := line.trim_space().split(': ')
|
||||
if parts.len < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
key := parts[0]
|
||||
value := parts[1]
|
||||
|
||||
if key.starts_with('interface') {
|
||||
if current_interface != '' {
|
||||
configs[current_interface] = WGInfo{
|
||||
interface_: iface
|
||||
peers: current_peers.clone()
|
||||
}
|
||||
current_peers.clear()
|
||||
}
|
||||
|
||||
current_interface = value
|
||||
iface = WGInterface{
|
||||
name: current_interface
|
||||
public_key: ''
|
||||
listening_port: 0
|
||||
}
|
||||
} else if key == 'public key' {
|
||||
iface.public_key = value
|
||||
} else if key == 'listening port' {
|
||||
iface.listening_port = value.int()
|
||||
} else if key.starts_with('peer') {
|
||||
peer_key = value
|
||||
mut peer := WGPeer{
|
||||
endpoint: ''
|
||||
allowed_ips: ''
|
||||
latest_handshake: ''
|
||||
transfer: ''
|
||||
persistent_keepalive: ''
|
||||
}
|
||||
current_peers[peer_key] = peer
|
||||
} else if key == 'endpoint' {
|
||||
current_peers[peer_key].endpoint = value
|
||||
} else if key == 'allowed ips' {
|
||||
current_peers[peer_key].allowed_ips = value
|
||||
} else if key == 'latest handshake' {
|
||||
current_peers[peer_key].latest_handshake = value
|
||||
} else if key == 'transfer' {
|
||||
current_peers[peer_key].transfer = value
|
||||
} else if key == 'persistent keepalive' {
|
||||
current_peers[peer_key].persistent_keepalive = value
|
||||
}
|
||||
}
|
||||
|
||||
if current_interface != '' {
|
||||
configs[current_interface] = WGInfo{
|
||||
interface_: iface
|
||||
peers: current_peers.clone()
|
||||
}
|
||||
}
|
||||
|
||||
return WGShow{
|
||||
configs: configs
|
||||
}
|
||||
}
|
||||
102
lib/clients/wireguard/wireguard_factory_.v
Normal file
102
lib/clients/wireguard/wireguard_factory_.v
Normal file
@@ -0,0 +1,102 @@
|
||||
module wireguard
|
||||
|
||||
import freeflowuniverse.herolib.core.base
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
|
||||
__global (
|
||||
wireguard_global map[string]&WireGuard
|
||||
wireguard_default string
|
||||
)
|
||||
|
||||
/////////FACTORY
|
||||
|
||||
@[params]
|
||||
pub struct ArgsGet {
|
||||
pub mut:
|
||||
name string
|
||||
}
|
||||
|
||||
fn args_get(args_ ArgsGet) ArgsGet {
|
||||
mut args := args_
|
||||
if args.name == '' {
|
||||
args.name = wireguard_default
|
||||
}
|
||||
if args.name == '' {
|
||||
args.name = 'wireguard'
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
pub fn get(args_ ArgsGet) !&WireGuard {
|
||||
mut args := args_get(args_)
|
||||
if args.name !in wireguard_global {
|
||||
if args.name == 'wireguard' {
|
||||
if !config_exists(args) {
|
||||
if default {
|
||||
println('When saving')
|
||||
config_save(args)!
|
||||
}
|
||||
}
|
||||
config_load(args)!
|
||||
}
|
||||
}
|
||||
return wireguard_global[args.name] or {
|
||||
println(wireguard_global)
|
||||
panic('could not get config for wireguard with name:${args.name}')
|
||||
}
|
||||
}
|
||||
|
||||
fn config_exists(args_ ArgsGet) bool {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context() or { panic('bug') }
|
||||
return context.hero_config_exists('wireguard', args.name)
|
||||
}
|
||||
|
||||
fn config_load(args_ ArgsGet) ! {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context()!
|
||||
mut heroscript := context.hero_config_get('wireguard', args.name)!
|
||||
play(heroscript: heroscript)!
|
||||
}
|
||||
|
||||
fn config_save(args_ ArgsGet) ! {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context()!
|
||||
context.hero_config_set('wireguard', args.name, heroscript_default()!)!
|
||||
}
|
||||
|
||||
fn set(o WireGuard) ! {
|
||||
mut o2 := obj_init(o)!
|
||||
wireguard_global[o.name] = &o2
|
||||
wireguard_default = o.name
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct PlayArgs {
|
||||
pub mut:
|
||||
heroscript string // if filled in then plbook will be made out of it
|
||||
plbook ?playbook.PlayBook
|
||||
reset bool
|
||||
}
|
||||
|
||||
pub fn play(args_ PlayArgs) ! {
|
||||
mut args := args_
|
||||
|
||||
if args.heroscript == '' {
|
||||
args.heroscript = heroscript_default()!
|
||||
}
|
||||
mut plbook := args.plbook or { playbook.new(text: args.heroscript)! }
|
||||
|
||||
mut install_actions := plbook.find(filter: 'wireguard.configure')!
|
||||
if install_actions.len > 0 {
|
||||
for install_action in install_actions {
|
||||
mut p := install_action.params
|
||||
cfg_play(p)!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// switch instance to be used for wireguard
|
||||
pub fn switch(name string) {
|
||||
wireguard_default = name
|
||||
}
|
||||
38
lib/clients/wireguard/wireguard_model.v
Normal file
38
lib/clients/wireguard/wireguard_model.v
Normal file
@@ -0,0 +1,38 @@
|
||||
module wireguard
|
||||
|
||||
import freeflowuniverse.herolib.data.paramsparser
|
||||
|
||||
pub const version = '1.14.3'
|
||||
const singleton = false
|
||||
const default = true
|
||||
|
||||
// TODO: THIS IS EXAMPLE CODE AND NEEDS TO BE CHANGED IN LINE TO STRUCT BELOW, IS STRUCTURED AS HEROSCRIPT
|
||||
pub fn heroscript_default() !string {
|
||||
heroscript := "
|
||||
!!wireguard.configure
|
||||
name:'wireguard'
|
||||
"
|
||||
return heroscript
|
||||
}
|
||||
|
||||
// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED
|
||||
|
||||
@[heap]
|
||||
pub struct WireGuard {
|
||||
pub mut:
|
||||
name string = 'wireguard'
|
||||
}
|
||||
|
||||
fn cfg_play(p paramsparser.Params) ! {
|
||||
// THIS IS EXAMPLE CODE AND NEEDS TO BE CHANGED IN LINE WITH struct above
|
||||
mut mycfg := WireGuard{
|
||||
name: p.get_default('name', 'wireguard')!
|
||||
}
|
||||
set(mycfg)!
|
||||
}
|
||||
|
||||
fn obj_init(obj_ WireGuard) !WireGuard {
|
||||
// never call get here, only thing we can do here is work on object itself
|
||||
mut obj := obj_
|
||||
return obj
|
||||
}
|
||||
13
lib/installers/net/wireguard/.heroscript
Normal file
13
lib/installers/net/wireguard/.heroscript
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
!!hero_code.generate_installer
|
||||
name:'wireguard_installer'
|
||||
classname:'WireGuard'
|
||||
singleton:0
|
||||
templates:0
|
||||
default:1
|
||||
title:''
|
||||
supported_platforms:''
|
||||
reset:0
|
||||
startupmanager:0
|
||||
hasconfig:0
|
||||
build:0
|
||||
44
lib/installers/net/wireguard/readme.md
Normal file
44
lib/installers/net/wireguard/readme.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# wireguard
|
||||
|
||||
|
||||
|
||||
To get started
|
||||
|
||||
```vlang
|
||||
|
||||
|
||||
import freeflowuniverse.herolib.installers.something.wireguard as wireguard_installer
|
||||
|
||||
heroscript:="
|
||||
!!wireguard.configure name:'test'
|
||||
password: '1234'
|
||||
port: 7701
|
||||
|
||||
!!wireguard.start name:'test' reset:1
|
||||
"
|
||||
|
||||
wireguard_installer.play(heroscript=heroscript)!
|
||||
|
||||
//or we can call the default and do a start with reset
|
||||
//mut installer:= wireguard_installer.get()!
|
||||
//installer.start(reset:true)!
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
## example heroscript
|
||||
|
||||
```hero
|
||||
!!wireguard.configure
|
||||
homedir: '/home/user/wireguard'
|
||||
username: 'admin'
|
||||
password: 'secretpassword'
|
||||
title: 'Some Title'
|
||||
host: 'localhost'
|
||||
port: 8888
|
||||
|
||||
```
|
||||
|
||||
|
||||
59
lib/installers/net/wireguard/wireguard_actions.v
Normal file
59
lib/installers/net/wireguard/wireguard_actions.v
Normal file
@@ -0,0 +1,59 @@
|
||||
module wireguard
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.installers.ulist
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core
|
||||
|
||||
//////////////////// following actions are not specific to instance of the object
|
||||
|
||||
// checks if a certain version or above is installed
|
||||
fn installed() !bool {
|
||||
osal.execute_silent('wg --version') or { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
// get the Upload List of the files
|
||||
fn ulist_get() !ulist.UList {
|
||||
return ulist.UList{}
|
||||
}
|
||||
|
||||
// uploads to S3 server if configured
|
||||
fn upload() ! {
|
||||
}
|
||||
|
||||
fn install() ! {
|
||||
console.print_header('install wireguard')
|
||||
|
||||
cmd := match core.platform()! {
|
||||
.ubuntu {
|
||||
'sudo apt install -y wireguard'
|
||||
}
|
||||
.osx {
|
||||
'sudo brew install -y wireguard-tools'
|
||||
}
|
||||
else {
|
||||
return error('unsupported platfrom ${core.platform()!}')
|
||||
}
|
||||
}
|
||||
|
||||
osal.execute_stdout(cmd)!
|
||||
}
|
||||
|
||||
fn destroy() ! {
|
||||
console.print_header('uninstall wireguard')
|
||||
|
||||
cmd := match core.platform()! {
|
||||
.ubuntu {
|
||||
'sudo apt remove -y wireguard wireguard-tools'
|
||||
}
|
||||
.osx {
|
||||
'sudo brew uninstall -y wireguard-tools'
|
||||
}
|
||||
else {
|
||||
return error('unsupported platform ${core.platform()!}')
|
||||
}
|
||||
}
|
||||
|
||||
osal.execute_stdout(cmd)!
|
||||
}
|
||||
74
lib/installers/net/wireguard/wireguard_factory_.v
Normal file
74
lib/installers/net/wireguard/wireguard_factory_.v
Normal file
@@ -0,0 +1,74 @@
|
||||
module wireguard
|
||||
|
||||
import freeflowuniverse.herolib.core.base
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.sysadmin.startupmanager
|
||||
import freeflowuniverse.herolib.osal.zinit
|
||||
import time
|
||||
|
||||
__global (
|
||||
wireguard_installer_global map[string]&WireGuard
|
||||
wireguard_installer_default string
|
||||
)
|
||||
|
||||
/////////FACTORY
|
||||
|
||||
@[params]
|
||||
pub struct ArgsGet {
|
||||
pub mut:
|
||||
name string
|
||||
}
|
||||
|
||||
pub fn get(args_ ArgsGet) !&WireGuard {
|
||||
return &WireGuard{}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS ///////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager {
|
||||
// unknown
|
||||
// screen
|
||||
// zinit
|
||||
// tmux
|
||||
// systemd
|
||||
match cat {
|
||||
.zinit {
|
||||
console.print_debug('startupmanager: zinit')
|
||||
return startupmanager.get(cat: .zinit)!
|
||||
}
|
||||
.systemd {
|
||||
console.print_debug('startupmanager: systemd')
|
||||
return startupmanager.get(cat: .systemd)!
|
||||
}
|
||||
else {
|
||||
console.print_debug('startupmanager: auto')
|
||||
return startupmanager.get()!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct InstallArgs {
|
||||
pub mut:
|
||||
reset bool
|
||||
}
|
||||
|
||||
pub fn (mut self WireGuard) install(args InstallArgs) ! {
|
||||
switch(self.name)
|
||||
if args.reset || (!installed()!) {
|
||||
install()!
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut self WireGuard) destroy() ! {
|
||||
switch(self.name)
|
||||
destroy()!
|
||||
}
|
||||
|
||||
// switch instance to be used for wireguard_installer
|
||||
pub fn switch(name string) {
|
||||
wireguard_installer_default = name
|
||||
}
|
||||
23
lib/installers/net/wireguard/wireguard_model.v
Normal file
23
lib/installers/net/wireguard/wireguard_model.v
Normal file
@@ -0,0 +1,23 @@
|
||||
module wireguard
|
||||
|
||||
pub const version = '1.14.3'
|
||||
const singleton = false
|
||||
const default = true
|
||||
|
||||
// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED
|
||||
@[heap]
|
||||
pub struct WireGuard {
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
}
|
||||
|
||||
fn obj_init(obj_ WireGuard) !WireGuard {
|
||||
// never call get here, only thing we can do here is work on object itself
|
||||
mut obj := obj_
|
||||
return obj
|
||||
}
|
||||
|
||||
// called before start if done
|
||||
fn configure() ! {
|
||||
// mut installer := get()!
|
||||
}
|
||||
Reference in New Issue
Block a user