summaryrefslogtreecommitdiff
path: root/cmd/cli/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/cli/main.go')
-rw-r--r--cmd/cli/main.go196
1 files changed, 179 insertions, 17 deletions
diff --git a/cmd/cli/main.go b/cmd/cli/main.go
index c31716f..17348c9 100644
--- a/cmd/cli/main.go
+++ b/cmd/cli/main.go
@@ -1,9 +1,13 @@
package main
import (
+ "encoding/json"
"flag"
"fmt"
+ "os"
"os/exec"
+ "path"
+ "path/filepath"
"strings"
eduvpn "github.com/jwijenbergh/eduvpn-common"
@@ -15,39 +19,197 @@ func openBrowser(urlString string) {
exec.Command("xdg-open", urlString).Start()
}
-func logState(oldState string, newState string, data string) {
- fmt.Printf("State: %s -> State: %s with data %s\n", oldState, newState, data)
+// Taken from internal/server.go as it's an internal API for now
+type ServerProfile struct {
+ ID string `json:"profile_id"`
+ DisplayName string `json:"display_name"`
+ VPNProtoList []string `json:"vpn_proto_list"`
+ DefaultGateway bool `json:"default_gateway"`
+}
+
+type ServerProfileInfo struct {
+ Current string `json:"current_profile"`
+ Info struct {
+ ProfileList []ServerProfile `json:"profile_list"`
+ } `json:"info"`
+}
+
+func sendProfile(state *eduvpn.VPNState, data string) {
+ fmt.Printf("Multiple VPN profiles found. Please select a profile by entering e.g. 1")
+ serverProfiles := &ServerProfileInfo{}
+
+ jsonErr := json.Unmarshal([]byte(data), &serverProfiles)
+ if jsonErr != nil {
+ fmt.Println("\nFailed to get profile list", jsonErr)
+ return
+ }
+
+ var profiles string
+
+ for index, profile := range serverProfiles.Info.ProfileList {
+ profiles += fmt.Sprintf("\n%d - %s", index+1, profile.DisplayName)
+ }
+
+ // Show the profiles
+ fmt.Println(profiles)
+
+ var chosenProfile int
+ _, scanErr := fmt.Scanf("%d", &chosenProfile)
+
+ if scanErr != nil || chosenProfile <= 0 || chosenProfile > len(serverProfiles.Info.ProfileList) {
+ fmt.Println("invalid profile chosen, please retry")
+ sendProfile(state, data)
+ return
+ }
+
+ profile := serverProfiles.Info.ProfileList[chosenProfile-1]
+ fmt.Println("Sending profile ID", profile.ID)
+ profileErr := state.SetProfileID(profile.ID)
+
+ if profileErr != nil {
+ fmt.Println("Failed setting profile with error", profileErr)
+ }
+}
+
+func stateCallback(state *eduvpn.VPNState, oldState string, newState string, data string) {
if newState == "OAuth_Started" {
openBrowser(data)
}
+
+ if newState == "Ask_Profile" {
+ sendProfile(state, data)
+ }
}
-func main() {
- urlArg := flag.String("url", "", "The url of the vpn")
- flag.Parse()
+func getConfig(url string, isInstitute bool) (string, error) {
+ if !strings.HasPrefix(url, "https://") {
+ url = "https://" + url
+ }
+ state := &eduvpn.VPNState{}
+ state.Register("org.eduvpn.app.linux", "configs", func(old string, new string, data string) {
+ stateCallback(state, old, new, data)
+ }, false)
- urlString := *urlArg
+ defer state.Deregister()
- if urlString != "" {
- if !strings.HasPrefix(urlString, "https://") {
- urlString = "https://" + urlString
+ if isInstitute {
+ return state.ConnectInstituteAccess(url)
+ }
+ return state.ConnectSecureInternet(url)
+}
+
+type ServerDiscoEntry struct {
+ ServerType string `json:"server_type"`
+ BaseURL string `json:"base_url"`
+}
+
+func getAllSecureInternetServers(serverList string) ([]string, error) {
+ var secureInternet []string
+
+ discoEntries := []ServerDiscoEntry{}
+
+ jsonErr := json.Unmarshal([]byte(serverList), &discoEntries)
+
+ if jsonErr != nil {
+ return nil, jsonErr
+ }
+
+ for _, entry := range discoEntries {
+ if entry.ServerType == "secure_internet" {
+ secureInternet = append(secureInternet, entry.BaseURL)
}
+ }
+
+ return secureInternet, nil
+}
+
+func storeSecureInternetConfig(state *eduvpn.VPNState, url string, directory string) {
+ os.MkdirAll(directory, os.ModePerm)
+
+ fmt.Println("Creating and storing cert for", url)
+
+ config, configErr := getConfig(url, false)
+
+ if configErr != nil {
+ fmt.Printf("Failed obtaining config for url %s with error %v\n", url, configErr)
+ }
+
+ cleanURL := filepath.Base(url)
+
+ writeErr := os.WriteFile(path.Join(directory, cleanURL), []byte(config), 0o644)
+ if writeErr != nil {
+ fmt.Printf("Failed writing config for url %s with error %v\n", url, writeErr)
+ }
+}
+
+func getSecureInternetAll(homeURL string) {
+ state := &eduvpn.VPNState{}
+
+ state.Register("org.eduvpn.app.linux", "configs", func(old string, new string, data string) {
+ stateCallback(state, old, new, data)
+ }, false)
+
+ // Get the disco servers
+ servers, serversErr := state.GetDiscoServers()
+
+ if serversErr != nil {
+ fmt.Println("Cannot obtain servers", serversErr)
+ return
+ }
- state := &eduvpn.VPNState{}
+ secureInternetURLs, secureInternetErr := getAllSecureInternetServers(servers)
- state.Register("org.eduvpn.app.linux", "configs", logState, true)
- config, configErr := state.Connect(urlString)
+ if secureInternetErr != nil {
+ fmt.Println("Cannot parse secure internet servers", secureInternetErr)
+ return
+ }
+
+ // Ensure that the directory exists
+ directory := "certs"
+ os.MkdirAll(directory, os.ModePerm)
- if configErr != nil {
- fmt.Printf("Config error %v", configErr)
- return
+ // Obtain config for home server
+ storeSecureInternetConfig(state, homeURL, directory)
+
+ for _, serverURL := range secureInternetURLs {
+ if !strings.Contains(serverURL, homeURL) {
+ storeSecureInternetConfig(state, serverURL, directory)
}
+ }
+
+ fmt.Println("Done storing all certs in directory:", directory)
+}
+
+func printConfig(url string, isInstitute bool) {
+ config, configErr := getConfig(url, isInstitute)
+
+ if configErr != nil {
+ fmt.Println("Error getting config", configErr)
+ return
+ }
- fmt.Println(config)
+ fmt.Println("Obtained config", config)
+}
- state.Deregister()
+func main() {
+ urlArg := flag.String("get-institute", "", "The url of an institute to connect to")
+ secureInternet := flag.String("get-secure", "", "Gets secure internet servers.")
+ secureInternetAll := flag.String("get-secure-all", "", "Gets certificates for all secure internet servers. It stores them in ./certs. Provide an URL for the home server e.g. nl.eduvpn.org.")
+ flag.Parse()
+ // Connect to a VPN by getting an Institute Access config
+ urlString := *urlArg
+ secureInternetString := *secureInternet
+ secureInternetAllString := *secureInternetAll
+ if urlString != "" {
+ printConfig(urlString, true)
+ return
+ } else if secureInternetString != "" {
+ printConfig(secureInternetString, false)
+ return
+ } else if secureInternetAllString != "" {
+ getSecureInternetAll(secureInternetAllString)
return
}