Skip to content

Commit

Permalink
feat: basic agent cli added to setup wireguard
Browse files Browse the repository at this point in the history
  • Loading branch information
tanmoysrt committed Jan 30, 2025
1 parent 0c37585 commit d04b977
Show file tree
Hide file tree
Showing 5 changed files with 314 additions and 115 deletions.
3 changes: 2 additions & 1 deletion agent/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ agent.db
agent.db-*
docs.txt
agent
swiftwave-agent
swiftwave-agent
*.bak
196 changes: 175 additions & 21 deletions agent/cli.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
package main

import (
"context"
"fmt"
"os"
"strconv"

"github.com/coreos/go-iptables/iptables"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
"github.com/spf13/cobra"
"github.com/vishvananda/netlink"
)

func init() {
rootCmd.AddCommand(startCmd)
rootCmd.AddCommand(setConfigCmd)
rootCmd.AddCommand(setupCmd)
rootCmd.AddCommand(getConfig)
rootCmd.AddCommand(syncDockerBridge)
rootCmd.AddCommand(cleanup)

setConfigCmd.Flags().String("wireguard-private-key", "", "Wireguard private key")
setConfigCmd.Flags().String("wireguard-address", "", "Wireguard address")
setConfigCmd.Flags().Int("wireguard-cidr", 0, "Wireguard CIDR")
setConfigCmd.Flags().String("docker-network-gateway-address", "", "Docker network gateway address")
setConfigCmd.Flags().String("docker-network-subnet", "", "Docker network subnet")
setConfigCmd.Flags().Int("docker-network-cidr", 0, "Docker network CIDR")
setConfigCmd.MarkFlagRequired("wireguard-private-key")
setConfigCmd.MarkFlagRequired("wireguard-address")
setConfigCmd.MarkFlagRequired("wireguard-cidr")
setConfigCmd.MarkFlagRequired("docker-network-gateway-address")
setConfigCmd.MarkFlagRequired("docker-network-subnet")
setConfigCmd.MarkFlagRequired("docker-network-cidr")
setupCmd.Flags().String("wireguard-private-key", "", "Wireguard private key")
setupCmd.Flags().String("wireguard-address", "", "Wireguard address")
setupCmd.Flags().Int("wireguard-cidr", 0, "Wireguard CIDR")
setupCmd.Flags().String("docker-network-gateway-address", "", "Docker network gateway address")
setupCmd.Flags().String("docker-network-subnet", "", "Docker network subnet")
setupCmd.Flags().Int("docker-network-cidr", 0, "Docker network CIDR")
setupCmd.MarkFlagRequired("wireguard-private-key")
setupCmd.MarkFlagRequired("wireguard-address")
setupCmd.MarkFlagRequired("wireguard-cidr")
setupCmd.MarkFlagRequired("docker-network-gateway-address")
setupCmd.MarkFlagRequired("docker-network-subnet")
setupCmd.MarkFlagRequired("docker-network-cidr")

}

Expand All @@ -42,15 +51,24 @@ var startCmd = &cobra.Command{
},
}

var setConfigCmd = &cobra.Command{
Use: "set-config",
var setupCmd = &cobra.Command{
Use: "setup",
Run: func(cmd *cobra.Command, args []string) {
existingConfig, err := GetConfig()
if err == nil {
fmt.Println(existingConfig)
if existingConfig.WireguardConfig.PrivateKey != "" {
cmd.Println("Sorry, you can't change any config")
return
}
}

wireguard_cidr, err := strconv.Atoi(cmd.Flag("wireguard-cidr").Value.String())
if err != nil {
cmd.PrintErr("Invalid wireguard cidr")
return
}
docker_cidr, err := strconv.Atoi(cmd.Flag("docker-cidr").Value.String())
docker_cidr, err := strconv.Atoi(cmd.Flag("docker-network-cidr").Value.String())
if err != nil {
cmd.PrintErr("Invalid docker cidr")
return
Expand All @@ -62,18 +80,54 @@ var setConfigCmd = &cobra.Command{
CIDR: wireguard_cidr,
},
DockerNetwork: DockerNetworkConfig{
GatewayAddress: cmd.Flag("docker-gateway-address").Value.String(),
Subnet: cmd.Flag("docker-subnet").Value.String(),
GatewayAddress: cmd.Flag("docker-network-gateway-address").Value.String(),
Subnet: cmd.Flag("docker-network-subnet").Value.String(),
CIDR: docker_cidr,
},
}
err = SetConfig(&config)

tx := rwDB.Begin()
defer tx.Rollback()

err = SetConfig(tx, &config)
if err != nil {
cmd.PrintErr(err.Error())
return
}
// Create docker network if it doesn't exist
err = config.CreateDockerNetwork(tx)
if err != nil {
cmd.PrintErr(err.Error())
return
}
tx.Commit()
cmd.Println("Config updated")
},
}

var syncDockerBridge = &cobra.Command{
Use: "sync-docker-bridge",
Run: func(cmd *cobra.Command, args []string) {
// Check if docker network bridge exists
_, err := dockerClient.NetworkInspect(context.TODO(), DockerNetworkName, network.InspectOptions{})
if err != nil {
cmd.Println("Docker network bridge doesn't exist")
cmd.PrintErr(err.Error())
return
}
// Set docker network bridge id
config, err := GetConfig()
if err != nil {
cmd.PrintErr(err.Error())
return
}
config.DockerNetwork.BridgeId = fmt.Sprintf("br-%s", config.DockerNetwork.BridgeId[:12])
err = SetConfig(rwDB, config)
if err != nil {
cmd.PrintErr(err.Error())
return
} else {
cmd.Println("Config updated")
}
cmd.Println("Docker network bridge info synced")
},
}

Expand All @@ -91,8 +145,108 @@ var getConfig = &cobra.Command{
cmd.Printf(" • CIDR -------------- %d\n", config.WireguardConfig.CIDR)
cmd.Println()
cmd.Println("Docker Network Configuration:")
cmd.Printf(" • Bridge ID ---------- %s\n", config.DockerNetwork.BridgeId)
cmd.Printf(" • Gateway Address ---- %s\n", config.DockerNetwork.GatewayAddress)
cmd.Printf(" • Subnet ------------- %s\n", config.DockerNetwork.Subnet)
cmd.Printf(" • CIDR -------------- %d\n", config.DockerNetwork.CIDR)
},
}

var cleanup = &cobra.Command{
Use: "cleanup",
Run: func(cmd *cobra.Command, args []string) {
// Ask for confirmation
fmt.Println("This will delete all containers and remove docker and wireguard networks")
fmt.Println("Are you sure you want to continue? (y/n)")
var response string
_, err := fmt.Scanln(&response)
if err != nil {
cmd.PrintErr(err.Error())
return
}
if response != "y" {
cmd.Println("Aborting")
return
}
// Delete all containers
containers, err := dockerClient.ContainerList(context.TODO(), container.ListOptions{})
if err != nil {
cmd.PrintErr(err.Error())
cmd.Println("Failed to fetch containers")
return
}
for _, c := range containers {
if err := dockerClient.ContainerRemove(context.TODO(), c.ID, container.RemoveOptions{
Force: true,
RemoveVolumes: false,
RemoveLinks: true,
}); err != nil {
cmd.PrintErr(err.Error())
cmd.Println("Failed to remove container " + c.ID)
}
}
cmd.Println("Containers removed")

// Delete docker network
err = dockerClient.NetworkRemove(context.TODO(), DockerNetworkName)
if err != nil {
cmd.PrintErr("Failed to delete docker network\n")
cmd.PrintErr(err.Error())
cmd.Println()
} else {
cmd.Println("Docker network removed")
}
// Delete wireguard network
link, err := netlink.LinkByName(WireguardInterfaceName)
if err == nil {
err = netlink.LinkDel(link)
if err != nil {
cmd.PrintErr("Failed to delete wireguard interface")
cmd.PrintErr(err.Error())
} else {
cmd.Println("Wireguard interface removed")
}
}
// Flush all the iptables rules
ipt, err := iptables.New()
if err != nil {
cmd.PrintErr(err.Error())
return
}
err = ipt.ClearAll()
if err != nil {
cmd.PrintErr(err.Error())
return
}
// Backup and remove the database file
moveDBFilesToBackup()
// Done
cmd.Println("Cleanup completed")
},
}

func moveDBFilesToBackup() {
// Move the `dbName` file to `dbName.bak`
if _, err := os.Stat(dbName); err == nil {
if err := os.Rename(dbName, dbName+".bak"); err != nil {
fmt.Println(err.Error())
return
}
fmt.Println("Database file moved to " + dbName + ".bak")
}
// Also move the db-shm and db-wal files to db-shm.bak and db-wal.bak
if _, err := os.Stat(dbName + "-shm"); err == nil {
if err := os.Rename(dbName+"-shm", dbName+"-shm.bak"); err != nil {
fmt.Println(err.Error())
return
}
fmt.Println("Database shm file moved to " + dbName + "-shm.bak")
}
if _, err := os.Stat(dbName + "-wal"); err == nil {
if err := os.Rename(dbName+"-wal", dbName+"-wal.bak"); err != nil {
fmt.Println(err.Error())
return
}
fmt.Println("Database wal file moved to " + dbName + "-wal.bak")
}
}
16 changes: 10 additions & 6 deletions agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
)

type AgentConfig struct {
ID uint `gorm:"primaryKey"`
WireguardConfig WireguardConfig `json:"wireguard_config" gorm:"embedded;embeddedPrefix:wireguard_"`
DockerNetwork DockerNetworkConfig `json:"docker_network" gorm:"embedded;embeddedPrefix:docker_network_"`
}
Expand All @@ -28,24 +29,27 @@ func GetConfig() (*AgentConfig, error) {
var config AgentConfig
if err := rDB.First(&config).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return &AgentConfig{}, nil
return &AgentConfig{
WireguardConfig: WireguardConfig{},
DockerNetwork: DockerNetworkConfig{},
}, nil
} else {
return nil, errors.New("error getting config")
}
}
return &config, nil
}

func SetConfig(config *AgentConfig) error {
func SetConfig(db *gorm.DB, config *AgentConfig) error {
// Check if the config already exists
var count int64
if err := rDB.Model(&AgentConfig{}).Count(&count).Error; err != nil {
if err := db.Model(&AgentConfig{}).Count(&count).Error; err != nil {
return err
}
config.ID = 1 // set so that it can be updated
if count > 0 {
// Update the existing config
return rDB.Save(config).Error
return db.Save(config).Error
}
// Create a new config
return rDB.Create(config).Error
return db.Create(config).Error
}
2 changes: 1 addition & 1 deletion agent/db_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func MigrateDatabase() error {
func OpenSqliteDatabase(file string, readonly bool) (*gorm.DB, error) {
dbString := SQLiteDbString(file, readonly)
gormDb, err := gorm.Open(sqlite.Open(dbString), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
Logger: logger.Default.LogMode(logger.Silent),
})
if err != nil {
return nil, err
Expand Down
Loading

0 comments on commit d04b977

Please sign in to comment.