feat (tfgrid3deployer): add more support for wireguard
- support adding multiple user access endpoints to a network - support connecting gateways over wireguard Co-authored-by: mahmoud <mahmmoud.hassanein@gmail.com>
This commit is contained in:
25
examples/threefold/tfgrid3deployer/gw_over_wireguard/gw_over_wireguard.vsh
Normal file → Executable file
25
examples/threefold/tfgrid3deployer/gw_over_wireguard/gw_over_wireguard.vsh
Normal file → Executable file
@@ -11,11 +11,12 @@ griddriver.install()!
|
||||
|
||||
v := tfgrid3deployer.get()!
|
||||
println('cred: ${v}')
|
||||
deployment_name := 'vm_caddy1'
|
||||
deployment_name := 'wireguard_dep_example'
|
||||
mut deployment := tfgrid3deployer.new_deployment(deployment_name)!
|
||||
deployment.add_network(ip_range: '1.1.1.1/16', user_access: 5)
|
||||
|
||||
deployment.configure_network(user_access_endpoints: 3)!
|
||||
deployment.add_machine(
|
||||
name: 'vm_caddy1'
|
||||
name: 'vm1'
|
||||
cpu: 1
|
||||
memory: 2
|
||||
planetary: false
|
||||
@@ -25,12 +26,22 @@ deployment.add_machine(
|
||||
)
|
||||
deployment.deploy()!
|
||||
|
||||
vm1 := deployment.vm_get('vm_caddy1')!
|
||||
vm1 := deployment.vm_get('vm1')!
|
||||
println('vm1 info: ${vm1}')
|
||||
|
||||
vm1_public_ip4 := vm1.public_ip4.all_before('/')
|
||||
user_access_configs := deployment.get_user_access_configs()
|
||||
for config in user_access_configs {
|
||||
println('config:\n------\n${config.print_wg_config()}\n------\n')
|
||||
}
|
||||
|
||||
deployment.add_webname(name: 'gwnamecaddy', backend: 'http://${vm1_public_ip4}:80', use_wireguard: true)
|
||||
deployment.add_webname(
|
||||
name: 'gwoverwg'
|
||||
backend: 'http://${vm1.wireguard_ip}:8000'
|
||||
use_wireguard_network: true
|
||||
)
|
||||
deployment.deploy()!
|
||||
gw1 := deployment.webname_get('gwnamecaddy')!
|
||||
|
||||
gw1 := deployment.webname_get('gwoverwg')!
|
||||
println('gw info: ${gw1}')
|
||||
|
||||
// tfgrid3deployer.delete_deployment(deployment_name)!
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
module tfgrid3deployer
|
||||
|
||||
import freeflowuniverse.herolib.threefold.grid.models as grid_models
|
||||
import freeflowuniverse.herolib.threefold.gridproxy.model as gridproxy_models
|
||||
import freeflowuniverse.herolib.threefold.grid
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import compress.zlib
|
||||
@@ -9,7 +8,6 @@ import encoding.hex
|
||||
import x.crypto.chacha20
|
||||
import crypto.sha256
|
||||
import json
|
||||
import rand
|
||||
|
||||
struct GridContracts {
|
||||
pub mut:
|
||||
@@ -285,10 +283,10 @@ fn (mut self TFDeployment) finalize_deployment(setup DeploymentSetup) ! {
|
||||
}
|
||||
}
|
||||
|
||||
self.update_state(name_contracts_map, returned_deployments)!
|
||||
self.update_state(setup, name_contracts_map, returned_deployments)!
|
||||
}
|
||||
|
||||
fn (mut self TFDeployment) update_state(name_contracts_map map[string]u64, dls map[u32]&grid_models.Deployment) ! {
|
||||
fn (mut self TFDeployment) update_state(setup DeploymentSetup, name_contracts_map map[string]u64, dls map[u32]&grid_models.Deployment) ! {
|
||||
mut workloads := map[u32]map[string]&grid_models.Workload{}
|
||||
|
||||
for node_id, deployment in dls {
|
||||
@@ -339,6 +337,10 @@ fn (mut self TFDeployment) update_state(name_contracts_map map[string]u64, dls m
|
||||
wn.node_contract_id = dls[wn.node_id].contract_id
|
||||
wn.name_contract_id = name_contracts_map[wn.requirements.name]
|
||||
}
|
||||
|
||||
self.network.ip_range = setup.network_handler.ip_range
|
||||
self.network.mycelium = setup.network_handler.mycelium
|
||||
self.network.user_access_configs = setup.network_handler.user_access_configs.clone()
|
||||
}
|
||||
|
||||
pub fn (mut self TFDeployment) vm_get(vm_name string) !VMachine {
|
||||
@@ -514,7 +516,10 @@ pub fn (mut self TFDeployment) list_deployments() !map[u32]grid_models.Deploymen
|
||||
return dls
|
||||
}
|
||||
|
||||
|
||||
pub fn (mut self TFDeployment) configure_network(req NetworkRequirements) ! {
|
||||
self.network.requirements = req
|
||||
}
|
||||
|
||||
pub fn (mut self TFDeployment) get_user_access_configs() []UserAccessConfig {
|
||||
return self.network.user_access_configs
|
||||
}
|
||||
|
||||
@@ -32,15 +32,15 @@ fn new_deployment_setup(network_specs NetworkSpecs, vms []VMachine, zdbs []ZDB,
|
||||
mut dls := DeploymentSetup{
|
||||
deployer: deployer
|
||||
network_handler: NetworkHandler{
|
||||
req: network_specs.requirements
|
||||
deployer: deployer
|
||||
network_name: network_specs.name
|
||||
mycelium: network_specs.mycelium
|
||||
ip_range: network_specs.ip_range
|
||||
user_access_configs: network_specs.user_access_configs.clone()
|
||||
}
|
||||
}
|
||||
|
||||
dls.setup_network_workloads(vms, old_deployments)!
|
||||
dls.setup_network_workloads(vms, webnames, old_deployments)!
|
||||
dls.setup_vm_workloads(vms)!
|
||||
dls.setup_zdb_workloads(zdbs)!
|
||||
dls.setup_webname_workloads(webnames)!
|
||||
@@ -68,9 +68,9 @@ fn (mut self DeploymentSetup) match_versions(old_dls map[u32]grid_models.Deploym
|
||||
// - st: Modified DeploymentSetup struct with network workloads set up
|
||||
// Returns:
|
||||
// - None
|
||||
fn (mut st DeploymentSetup) setup_network_workloads(vms []VMachine, old_deployments map[u32]grid_models.Deployment) ! {
|
||||
fn (mut st DeploymentSetup) setup_network_workloads(vms []VMachine, webnames []WebName, old_deployments map[u32]grid_models.Deployment) ! {
|
||||
st.network_handler.load_network_state(old_deployments)!
|
||||
st.network_handler.create_network(vms)!
|
||||
st.network_handler.create_network(vms, webnames)!
|
||||
data := st.network_handler.generate_workloads()!
|
||||
|
||||
for node_id, workload in data {
|
||||
@@ -177,6 +177,11 @@ fn (mut self DeploymentSetup) setup_webname_workloads(webnames []WebName) ! {
|
||||
tls_passthrough: req.tls_passthrough
|
||||
backends: [req.backend]
|
||||
name: gw_name
|
||||
network: if wn.requirements.use_wireguard_network {
|
||||
self.network_handler.req.name
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
|
||||
self.workloads[wn.node_id] << gw.to_workload(
|
||||
@@ -206,7 +211,7 @@ fn (mut self DeploymentSetup) set_zmachine_workload(vmachine VMachine, public_ip
|
||||
network: grid_models.ZmachineNetwork{
|
||||
interfaces: [
|
||||
grid_models.ZNetworkInterface{
|
||||
network: self.network_handler.network_name
|
||||
network: self.network_handler.req.name
|
||||
ip: if vmachine.wireguard_ip.len > 0 {
|
||||
used_ip_octets[vmachine.node_id] << vmachine.wireguard_ip.all_after_last('.').u8()
|
||||
vmachine.wireguard_ip
|
||||
@@ -219,7 +224,7 @@ fn (mut self DeploymentSetup) set_zmachine_workload(vmachine VMachine, public_ip
|
||||
planetary: vmachine.requirements.planetary
|
||||
mycelium: if mycelium := vmachine.requirements.mycelium {
|
||||
grid_models.MyceliumIP{
|
||||
network: self.network_handler.network_name
|
||||
network: self.network_handler.req.name
|
||||
hex_seed: mycelium.hex_seed
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -7,12 +7,13 @@ import json
|
||||
import rand
|
||||
|
||||
// NetworkInfo struct to represent network details
|
||||
|
||||
@[params]
|
||||
pub struct NetworkRequirements {
|
||||
pub:
|
||||
pub mut:
|
||||
name string = 'net' + rand.string(5)
|
||||
user_access_endpoints int
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct NetworkSpecs {
|
||||
pub mut:
|
||||
@@ -22,11 +23,26 @@ pub mut:
|
||||
user_access_configs []UserAccessConfig
|
||||
}
|
||||
|
||||
struct UserAccessConfig{
|
||||
pub struct UserAccessConfig {
|
||||
pub:
|
||||
ip string
|
||||
secret_key string
|
||||
public_key string
|
||||
|
||||
peer_public_key string
|
||||
network_ip_range string
|
||||
public_node_endpoint string
|
||||
}
|
||||
|
||||
pub fn (c UserAccessConfig) print_wg_config() string {
|
||||
return '[Interface]
|
||||
Address = ${c.ip}
|
||||
PrivateKey = ${c.secret_key}
|
||||
[Peer]
|
||||
PublicKey = ${c.peer_public_key}
|
||||
AllowedIPs = ${c.network_ip_range}, 100.64.0.0/16
|
||||
PersistentKeepalive = 25
|
||||
Endpoint = ${c.public_node_endpoint}'
|
||||
}
|
||||
|
||||
struct NetworkHandler {
|
||||
@@ -51,7 +67,7 @@ mut:
|
||||
}
|
||||
|
||||
// TODO: maybe rename to fill_network or something similar
|
||||
fn (mut self NetworkHandler) create_network(vmachines []VMachine) ! {
|
||||
fn (mut self NetworkHandler) create_network(vmachines []VMachine, webnames []WebName) ! {
|
||||
// Set nodes
|
||||
self.nodes = []
|
||||
|
||||
@@ -61,9 +77,16 @@ fn (mut self NetworkHandler) create_network(vmachines []VMachine) ! {
|
||||
}
|
||||
}
|
||||
|
||||
for webname in webnames {
|
||||
if webname.requirements.use_wireguard_network && !self.nodes.contains(webname.node_id) {
|
||||
self.nodes << webname.node_id
|
||||
}
|
||||
}
|
||||
|
||||
console.print_header('Network nodes: ${self.nodes}.')
|
||||
self.setup_wireguard_data()!
|
||||
self.setup_access_node()!
|
||||
self.setup_user_access()!
|
||||
}
|
||||
|
||||
fn (mut self NetworkHandler) generate_workload(node_id u32, peers []grid_models.Peer, mycleium_hex_key string) !grid_models.Workload {
|
||||
@@ -88,10 +111,11 @@ fn (mut self NetworkHandler) generate_workload(node_id u32, peers []grid_models.
|
||||
fn (mut self NetworkHandler) prepare_hidden_node_peers(node_id u32) ![]grid_models.Peer {
|
||||
mut peers := []grid_models.Peer{}
|
||||
if self.public_node != 0 {
|
||||
ip_range_oct := self.ip_range.all_before('/').split('.')
|
||||
peers << grid_models.Peer{
|
||||
subnet: self.wg_subnet[self.public_node]
|
||||
wireguard_public_key: self.wg_keys[self.public_node][1]
|
||||
allowed_ips: [self.ip_range, '100.64.0.0/16']
|
||||
allowed_ips: [self.ip_range, '100.64.${ip_range_oct[1]}.${ip_range_oct[2]}/24']
|
||||
endpoint: '${self.endpoints[self.public_node]}:${self.wg_ports[self.public_node]}'
|
||||
}
|
||||
}
|
||||
@@ -99,14 +123,6 @@ fn (mut self NetworkHandler) prepare_hidden_node_peers(node_id u32) ![]grid_mode
|
||||
}
|
||||
|
||||
fn (mut self NetworkHandler) setup_access_node() ! {
|
||||
// Case 1: Deployment on 28 which is hidden node
|
||||
// - Setup access node
|
||||
// Case 2: Deployment on 11 which is public node
|
||||
// - Already have the access node
|
||||
// Case 3: if the saved state has already public node.
|
||||
// - Check the new deployment if its node is hidden take the saved one
|
||||
// - if the access node is already set, that means we have set its values e.g. the wireguard port, keys
|
||||
|
||||
if self.req.user_access_endpoints == 0 && (self.hidden_nodes.len < 1 || self.nodes.len == 1) {
|
||||
self.public_node = 0
|
||||
return
|
||||
@@ -162,6 +178,26 @@ fn (mut self NetworkHandler) setup_access_node() ! {
|
||||
self.endpoints[self.public_node] = access_node.public_config.ipv4.split('/')[0]
|
||||
}
|
||||
|
||||
fn (mut self NetworkHandler) setup_user_access() ! {
|
||||
to_create_user_access := self.req.user_access_endpoints - self.user_access_configs.len
|
||||
if to_create_user_access < 0 {
|
||||
// TODO: support removing user access
|
||||
return error('removing user access is not supported')
|
||||
}
|
||||
|
||||
for i := 0; i < to_create_user_access; i++ {
|
||||
wg_keys := self.deployer.client.generate_wg_priv_key()!
|
||||
self.user_access_configs << UserAccessConfig{
|
||||
ip: self.calculate_subnet()!
|
||||
secret_key: wg_keys[0]
|
||||
public_key: wg_keys[1]
|
||||
peer_public_key: self.wg_keys[self.public_node][1]
|
||||
public_node_endpoint: '${self.endpoints[self.public_node]}:${self.wg_ports[self.public_node]}'
|
||||
network_ip_range: self.ip_range
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut self NetworkHandler) setup_wireguard_data() ! {
|
||||
console.print_header('Setting up network workload.')
|
||||
self.hidden_nodes, self.none_accessible_ip_ranges = [], []
|
||||
@@ -211,22 +247,6 @@ fn (mut self NetworkHandler) setup_wireguard_data() ! {
|
||||
self.none_accessible_ip_ranges << wireguard_routing_ip(self.wg_subnet[node_id])
|
||||
}
|
||||
}
|
||||
|
||||
to_create_user_access := self.req.user_access_endpoints - self.user_access_configs.len
|
||||
if to_create_user_access < 0{
|
||||
// TODO: support removing user access
|
||||
return error('removing user access is not supported')
|
||||
}
|
||||
|
||||
for i := 0; i<to_create_user_access; i++{
|
||||
wg_keys := self.deployer.client.generate_wg_priv_key()!
|
||||
self.user_access_configs << UserAccessConfig{
|
||||
ip: self.calculate_subnet()!
|
||||
secret_key: wg_keys[0]
|
||||
public_key: wg_keys[1]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn (mut self NetworkHandler) prepare_public_node_peers(node_id u32) ![]grid_models.Peer {
|
||||
@@ -265,7 +285,7 @@ fn (mut self NetworkHandler) prepare_public_node_peers(node_id u32) ![]grid_mode
|
||||
}
|
||||
|
||||
for user_access in self.user_access_configs {
|
||||
routing_ip := wireguard_routing_ip(subnet)
|
||||
routing_ip := wireguard_routing_ip(user_access.ip)
|
||||
|
||||
peers << grid_models.Peer{
|
||||
subnet: user_access.ip
|
||||
@@ -319,7 +339,7 @@ fn (mut self NetworkHandler) load_network_state(dls map[u32]grid_models.Deployme
|
||||
continue
|
||||
}
|
||||
|
||||
self.network_name = network_name
|
||||
self.req.name = network_name
|
||||
self.nodes << node_id
|
||||
self.ip_range = znet.ip_range
|
||||
self.wg_ports[node_id] = znet.wireguard_listen_port
|
||||
@@ -339,7 +359,11 @@ fn (mut self NetworkHandler) load_network_state(dls map[u32]grid_models.Deployme
|
||||
}
|
||||
|
||||
for subnet, endpoint in subnet_to_endpoint {
|
||||
node_id := subnet_node[subnet]
|
||||
node_id := subnet_node[subnet] or {
|
||||
// this maybe a user access, not a node
|
||||
continue
|
||||
}
|
||||
|
||||
if endpoint == '' {
|
||||
self.hidden_nodes << node_id
|
||||
continue
|
||||
@@ -368,5 +392,3 @@ fn (mut self NetworkHandler) generate_workloads() !map[u32]grid_models.Workload
|
||||
|
||||
return workloads
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ pub struct WebNameRequirements {
|
||||
pub mut:
|
||||
name string @[required]
|
||||
node_id ?u32
|
||||
use_wireguard_network bool
|
||||
// must be in the format ip:port if tls_passthrough is set, otherwise the format should be http://ip[:port]
|
||||
backend string @[required]
|
||||
use_wireguard bool
|
||||
|
||||
Reference in New Issue
Block a user