Skip to content
Snippets Groups Projects
Commit 338424b0 authored by Florent Gluck's avatar Florent Gluck
Browse files

Fixed bug in Makefile

WIP: nexus-exam, CA cert handling
parent b40dfbcb
Branches
No related tags found
No related merge requests found
......@@ -334,6 +334,7 @@ clean_clients:
@for arch in $(ARCHES_CLIENT); do \
/bin/rm -rf $(BUILD_DIR)/$$arch ;\
done
@rm $(BUILD_DIR)/$(NEXUSH_BINARY) $(BUILD_DIR)/$(NEXUSCLI_BINARY) $(BUILD_DIR)/$(NEXUS_EXAM_BINARY)
run_nexush: check_login_var $(BUILD_DIR)/$(NEXUSH_BINARY)
$< $(LOGIN)
......
......@@ -7,34 +7,22 @@ import (
"os"
"os/exec"
"path"
"strings"
"time"
g "gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/libclient/globals"
liblogin "gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/libclient/login"
libversion "gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/libclient/version"
libvm "gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/libclient/vm"
"gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/client/defaults"
e "gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/client/exec"
u "gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/client/utils"
"gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/client/version"
"gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/common/buildversion"
"gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/common/params"
"gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/common/vm"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
"github.com/go-resty/resty/v2"
"gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/client/defaults"
u "gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/client/utils"
"gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/client/version"
"gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/common/buildversion"
nc "gitedu.hesge.ch/flg_projects/nexus_vdi/nexus/libclient/nexusclient"
)
const (
windowTitle = "nexus-exam"
windowTitle = "nexus-exam"
connectToVMmsg = "Enter password to connect to your VM:"
)
......@@ -45,9 +33,7 @@ var (
//go:embed nexus_exam_pwd.val
nexus_exam_pwd string
exitFn func()
token string
client *nc.NexusClient
isAuthenticated bool
isServerUp bool
......@@ -55,28 +41,11 @@ var (
credentialsInputBox *widget.Form
)
func exit(code int) {
if exitFn != nil {
exitFn()
}
os.Exit(code)
}
func attachVM(parent fyne.Window, hostname, cert, pwd string) {
setHeaderToken()
p := params.VMAttachCreds{Pwd: pwd}
creds, err := libvm.VMGetAnySpiceCreds(p)
func attachVM(parent fyne.Window, pwd string) {
err := client.VMAttachFromPwd(pwd)
if err != nil {
errorPopup(parent, "Failed attaching to VM: "+err.Error())
return
} else {
go func(creds vm.VMSpiceCredentialsSerialized) {
_, err := e.RunRemoteViewer(hostname, cert, creds.Name, creds.SpicePort, creds.SpicePwd, true)
if err != nil {
errorPopup(parent, "Failed executing remote-viewer: "+err.Error())
}
}(*creds)
}
}
......@@ -86,12 +55,12 @@ func abortWindow(msg string) {
win := a.NewWindow(windowTitle)
win.SetOnClosed(func() {
win.Close()
exit(1)
os.Exit(1)
})
label := widget.NewLabel("FATAL: " + msg)
button := widget.NewButton("Quit", func() {
win.Close()
exit(1)
os.Exit(1)
})
content := container.NewPadded(container.NewVBox(label, button))
win.SetContent(content)
......@@ -119,12 +88,6 @@ func hypervisorCheck() {
}
}
func setHeaderToken() {
client := g.GetInstance().Client
client.SetHeader("Content-Type", "application/json")
client.SetHeader("Authorization", "Bearer "+token)
}
// Recurrently obtains a new JWT token so that the user session doesn't expire.
func refreshToken(parent fyne.Window) {
var err error
......@@ -133,8 +96,8 @@ func refreshToken(parent fyne.Window) {
if isServerUp {
if !isAuthenticated {
// Logins and obtains a JWT token.
u.Println(time.Now(), ": request GetToken")
token, err = liblogin.GetToken(nexus_exam_user, nexus_exam_pwd)
u.Println(time.Now(), ": initiate authentication")
_, err = client.Authenticate(nexus_exam_user, nexus_exam_pwd)
if err != nil {
statusLabel.SetText("ERROR: failed to authenticate")
u.PrintlnErr(time.Now(), ": failed to authenticate: "+err.Error())
......@@ -147,16 +110,14 @@ func refreshToken(parent fyne.Window) {
time.Sleep(60 * time.Second)
}
} else {
setHeaderToken()
u.Println(time.Now(), ": request RefreshToken")
refreshedToken, err := liblogin.RefreshToken()
u.Println(time.Now(), ": attempt to refresh token")
client.RefreshAuthToken()
if err != nil {
statusLabel.SetText("ERROR: failed to refresh token")
u.PrintlnErr(time.Now(), ": failed to refresh token: "+err.Error())
isAuthenticated = false
credentialsInputBox.Hide()
} else {
token = refreshedToken
statusLabel.SetText(connectToVMmsg)
u.Println(time.Now(), ": successfully refreshed token")
credentialsInputBox.Show()
......@@ -173,7 +134,7 @@ func checkServerUp(parent fyne.Window) {
for {
// Instead of implementing a keepalive service (on both server and client side),
// we simply use the server version route to know whether the server is up or down.
_, err := libversion.GetServerVersion()
_, err := client.GetServerVersion()
if err != nil {
u.Println(time.Now(), ": server is down: "+err.Error())
isServerUp = false
......@@ -188,6 +149,11 @@ func checkServerUp(parent fyne.Window) {
}
func run() int {
hypervisorCheck()
client = nc.New(defaults.NexusServer)
client.SetTimeout(4 * time.Second)
isServerUp = false
isAuthenticated = false
var appname = path.Base(os.Args[0])
......@@ -195,41 +161,6 @@ func run() int {
u.PrintlnErr(appname + " version " + clientVersion.String() + " (commit " + buildversion.GitCommit() + ")")
u.PrintlnErr("Built on " + buildversion.BuildDate())
hypervisorCheck()
if err := e.CheckRemoteViewer(); err != nil {
abortWindow(err.Error())
}
certPath, err := defaults.CreateCert()
if err != nil {
abortWindow("Failed creating certificate!")
}
// No embedded certificate, exit with a information message.
if certPath == "" {
abortWindow("Public certificate is missing!")
}
exitFn = func() { os.Remove(certPath) }
// This thread acts as a signal handler for SIGINT or SIGTERM.
// When one of these signals is received, the temporary certificate file is deleted.
// Without this "handler", the temporary certificate file wouldn't be deleted.
go func() {
u.WaitForSignals()
exit(1)
}()
parts := strings.Split(defaults.NexusServer, ":")
hostname := parts[0]
client := resty.New()
client.SetRootCertificate(certPath)
host := "https://" + defaults.NexusServer
g.Init(hostname, host, certPath, client)
client.SetTimeout(4 * time.Second)
// Checks the client version is compatible with the server's API.
// if !cmdVersion.CheckServerCompatibility("nexus-exam") {
// abortWindow("client version is incompatible with server!")
......@@ -257,7 +188,7 @@ func run() int {
{Text: "Password", Widget: pwdEntry},
},
OnSubmit: func() {
attachVM(win, hostname, certPath, pwdEntry.Text)
attachVM(win, pwdEntry.Text)
},
SubmitText: "Connect",
}
......@@ -274,5 +205,5 @@ func run() int {
}
func main() {
exit(run())
os.Exit(run())
}
......@@ -3,6 +3,7 @@ package nexusclient
import (
"crypto/tls"
"net/url"
"time"
"github.com/go-resty/resty/v2"
)
......@@ -30,3 +31,7 @@ func (nc *NexusClient) GetBaseURL() (string, error) {
}
return url.Hostname(), nil
}
func (nc *NexusClient) SetTimeout(timeout time.Duration) {
nc.client.SetTimeout(timeout)
}
......@@ -23,3 +23,11 @@ func (nc *NexusClient) GetServerVersion() (*params.Version, error) {
}
}
}
// TODO:
// - Expose a method that returns a message with the content below
// - Update nexush, nexus-cli and nexus-exam accordingly
//
// clientVersion := version.Get()
// u.PrintlnErr(appname + " version " + clientVersion.String() + " (commit " + buildversion.GitCommit() + ")")
// u.PrintlnErr("Built on " + buildversion.BuildDate())
......@@ -25,6 +25,10 @@ const (
stopVMs = "/vms/stop"
)
//========================================================================================
// Public functions
//========================================================================================
func (nc *NexusClient) VMCreate(p params.VMCreate) (*vm.VMNetworkSerialized, error) {
resp, err := nc.client.R().SetBody(p).Post("/vms")
if err != nil {
......@@ -88,39 +92,6 @@ func (nc *NexusClient) VMExportDir(vmName, vmID, dirToExport string) (string, er
}
}
func (nc *NexusClient) VMGetSpiceCreds(vmID string, p params.VMAttachCreds) (*vm.VMSpiceCredentialsSerialized, error) {
resp, err := nc.client.R().SetBody(p).Post("/vms/" + vmID + "/spicecreds")
if err != nil {
return nil, err
}
return handleResponse(resp)
}
func (nc *NexusClient) VMGetAnySpiceCreds(p params.VMAttachCreds) (*vm.VMSpiceCredentialsSerialized, error) {
resp, err := nc.client.R().SetBody(p).Post("/vms/spicecreds")
if err != nil {
return nil, err
}
return handleResponse(resp)
}
func handleResponse(resp *resty.Response) (*vm.VMSpiceCredentialsSerialized, error) {
if resp.IsSuccess() {
var creds vm.VMSpiceCredentialsSerialized
if err := json.Unmarshal(resp.Body(), &creds); err != nil {
return nil, errors.New("Failed deserializing VM spice credentials: " + err.Error())
}
if err := validator.New(validator.WithRequiredStructEnabled()).Struct(creds); err != nil {
return nil, errors.New("Failed validating VM spice credentials: " + err.Error())
}
return &creds, nil
} else {
return nil, response.ErrorToMsg(resp)
}
}
func (nc *NexusClient) VMDelAccess(vmID, vmName, email string) error {
resp, err := nc.client.R().Delete("/vms/" + vmID + "/access/" + email)
if err != nil {
......@@ -210,23 +181,6 @@ func (nc *NexusClient) VMStop(vmID string) error {
}
}
func (nc *NexusClient) vmIdToAttachCreds(vmID string) (*vm.VMAttachCredentialsSerialized, error) {
resp, err := nc.client.R().Get("/vms/" + vmID + "/attach")
if err != nil {
return nil, err
}
if resp.IsSuccess() {
vmCreds, err := deserializeVMCredentials(resp)
if err != nil {
return nil, err
}
return vmCreds, nil
} else {
return nil, response.ErrorToMsg(resp)
}
}
func (nc *NexusClient) VMAttachFromID(vmID string) error {
creds, err := nc.vmIdToAttachCreds(vmID)
if err != nil {
......@@ -255,7 +209,7 @@ func (nc *NexusClient) VMAttachFromCreds(v vm.VMAttachCredentialsSerialized) err
p := params.VMAttachCreds{Pwd: v.Pwd}
creds, err := nc.VMGetSpiceCreds(v.ID.String(), p)
creds, err := nc.vmGetSpiceCreds(v.ID.String(), p)
if err != nil {
return err
}
......@@ -284,7 +238,7 @@ func (nc *NexusClient) VMAttachFromPwd(pwd string) error {
p := params.VMAttachCreds{Pwd: pwd}
creds, err := nc.VMGetAnySpiceCreds(p)
creds, err := nc.vmGetAnySpiceCreds(p)
if err != nil {
return err
} else {
......@@ -363,6 +317,45 @@ func (nc *NexusClient) GetStopVMs() ([]vm.VMNetworkSerialized, error) {
return nc.getVMs(stopVMs)
}
func (nc *NexusClient) GetListVM(vmID string) (*vm.VMNetworkSerialized, error) {
resp, err := nc.client.R().Get("/vms/" + vmID)
if err != nil {
return nil, err
}
if resp.IsSuccess() {
vm, err := deserializeVM(resp)
if err != nil {
return nil, err
}
return vm, nil
} else {
return nil, response.ErrorToMsg(resp)
}
}
//========================================================================================
// Private functions
//========================================================================================
func (nc *NexusClient) vmGetSpiceCreds(vmID string, p params.VMAttachCreds) (*vm.VMSpiceCredentialsSerialized, error) {
resp, err := nc.client.R().SetBody(p).Post("/vms/" + vmID + "/spicecreds")
if err != nil {
return nil, err
}
return handleResponse(resp)
}
func (nc *NexusClient) vmGetAnySpiceCreds(p params.VMAttachCreds) (*vm.VMSpiceCredentialsSerialized, error) {
resp, err := nc.client.R().SetBody(p).Post("/vms/spicecreds")
if err != nil {
return nil, err
}
return handleResponse(resp)
}
func (nc *NexusClient) getVMs(route string) ([]vm.VMNetworkSerialized, error) {
resp, err := nc.client.R().Get(route)
if err != nil {
......@@ -380,18 +373,33 @@ func (nc *NexusClient) getVMs(route string) ([]vm.VMNetworkSerialized, error) {
}
}
func (nc *NexusClient) GetListVM(vmID string) (*vm.VMNetworkSerialized, error) {
resp, err := nc.client.R().Get("/vms/" + vmID)
func (nc *NexusClient) vmIdToAttachCreds(vmID string) (*vm.VMAttachCredentialsSerialized, error) {
resp, err := nc.client.R().Get("/vms/" + vmID + "/attach")
if err != nil {
return nil, err
}
if resp.IsSuccess() {
vm, err := deserializeVM(resp)
vmCreds, err := deserializeVMCredentials(resp)
if err != nil {
return nil, err
}
return vm, nil
return vmCreds, nil
} else {
return nil, response.ErrorToMsg(resp)
}
}
func handleResponse(resp *resty.Response) (*vm.VMSpiceCredentialsSerialized, error) {
if resp.IsSuccess() {
var creds vm.VMSpiceCredentialsSerialized
if err := json.Unmarshal(resp.Body(), &creds); err != nil {
return nil, errors.New("Failed deserializing VM spice credentials: " + err.Error())
}
if err := validator.New(validator.WithRequiredStructEnabled()).Struct(creds); err != nil {
return nil, errors.New("Failed validating VM spice credentials: " + err.Error())
}
return &creds, nil
} else {
return nil, response.ErrorToMsg(resp)
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment