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

ongoing work on merging/reworking server and client trees

parent 0ceace40
No related branches found
No related tags found
No related merge requests found
Showing
with 917 additions and 34 deletions
BASEDIR=src
help:
@echo "nexus-server installation script for development."
@echo ""
@echo "Available targets:"
@echo "install create initial config (initial user and certificates for localhost)"
@echo " and initial data files"
@echo "uninstall remove config and data files"
install: create_files copy_config create_certificates
@echo "Installing development environment"
@echo ""
@echo "Successfully installed development environment"
uninstall: $(BASEDIR)/config $(BASEDIR)/data
@echo "Uninstalling development environment"
@rm -rf $^
@echo "OK"
@echo "Successfully uninstalled development environment"
create_files:
@echo "Creating required file hierarchy in $(BASEDIR)"
@mkdir -p $(BASEDIR)/config/pki
@mkdir -p $(BASEDIR)/data/vms
@mkdir -p $(BASEDIR)/data/templates
@mkdir -p $(BASEDIR)/data/tmp
@echo "OK"
copy_config:
@echo "Copying initial users config"
@cp -n config/server/users.json $(BASEDIR)/config/
@echo "OK"
create_certificates:
@echo "Generating certificates"
@cd config/server/pki && ./gen-cert.sh
@echo "OK"
@cd ../../..
@echo "Moving certificates"
@mv -n config/server/pki/server-nexus $(BASEDIR)/config/pki/
@echo "OK"
......@@ -14,7 +14,7 @@ __check_defined = \
$(error Environment variable $1$(if $2, ($2)) must be set))
help:
@echo "nexus-server installation script."
@echo "nexus-server installation script for production."
@echo ""
@echo "Available targets:"
@echo "build build the nexus-server binaries [run as non-root]"
......@@ -34,13 +34,13 @@ check_prefix:
build:
@echo "Building nexus-server"
@cd src && go build -a .
@cd src/server && go build -a .
@echo "OK"
@echo "Building genpwd"
@cd tools/genpwd/src && go build -a .
@cd tools/genpwd && go build -a .
@echo "OK"
install: check_prefix prepare_install src/nexus-server tools/genpwd/src/genpwd create_user create_files copy_config copy_binaries create_certificates set_permissions install_service
install: check_prefix prepare_install src/server/nexus-server tools/genpwd/genpwd create_user create_files copy_config copy_binaries create_certificates set_permissions install_service
@echo ""
@echo "Successfully installed nexus-server into $(BASEDIR)"
......@@ -87,10 +87,10 @@ remove_files:
clean_build:
@echo "Cleaning up nexus-server"
@cd src && go clean .
@cd src/server && go clean .
@echo "OK"
@echo "Cleaning up genpwd"
@cd tools/genpwd/src && go clean .
@cd tools/genpwd && go clean .
@echo "OK"
remove_service:
......@@ -116,24 +116,24 @@ create_files:
copy_config:
@echo "Copying initial users config"
@cp -n conf/users.json $(BASEDIR)/config/
@cp -n config/server/users.json $(BASEDIR)/config/
@echo "OK"
copy_binaries:
@echo "Copying binaries"
@cp src/nexus-server $(BASEDIR)/bin
@cp tools/genpwd/src/genpwd $(BASEDIR)/bin
@cp src/server/nexus-server $(BASEDIR)/bin
@cp tools/genpwd/genpwd $(BASEDIR)/bin
@cp tools/template_creator $(BASEDIR)/bin
@cp tools/vm_run $(BASEDIR)/bin
@echo "OK"
create_certificates:
@echo "Generating certificates"
@cd pki && ./gen-cert.sh
@cd config/server/pki && ./gen-cert.sh
@echo "OK"
@cd ..
@cd ../../..
@echo "Moving certificates"
@mv -n pki/server-nexus $(BASEDIR)/config/pki/
@mv -n config/server/pki/server-nexus $(BASEDIR)/config/pki/
@echo "OK"
set_permissions:
......@@ -147,10 +147,10 @@ set_permissions:
install_service:
@echo "Copying nexus-server crond task"
@cp conf/nexus-server /etc/cron.d/
@cp config/server/nexus-server /etc/cron.d/
@echo "OK"
@echo "Copying nexus-server service file"
@sed s,_PREFIX_,$(PREFIX),g conf/nexus-server.service > /etc/systemd/system/nexus-server.service
@sed s,_PREFIX_,$(PREFIX),g config/server/nexus-server.service > /etc/systemd/system/nexus-server.service
@echo "OK"
@echo "Reloading systemd configuration"
@systemctl daemon-reload
......
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
# HOWTO build
# Building nexus clients
## Introduction
This document describes how to obtain the source codes and build the following client applications:
This document describes how to build the following nexus clients:
- `nexush`
- `nexus-cli`
- `nexus-exam`
## Getting the sources
`nexush`, `nexus-cli` and `nexus-exam`' source codes reside in the same git repository:
```{.shell}
git clone ssh://git@ssh.hesge.ch:10572/flg_projects/nexus_vdi/nexus-client.git nexus-client.git
```
If you didn't set up a public key in your gitlab account, use https instead:
```{.shell}
git clone https://gitedu.hesge.ch/flg_projects/nexus_vdi/nexus-client.git nexus-client.git
```
### Building nexush and nexus-cli
To build `nexush` or `nexus-cli` binaries, go into `nexus-client.git/src/nexush` or `nexus-client.git/src/nexus-cli` and run:
To build `nexush` or `nexus-cli` binaries, go into `src/nexush` or `src/nexus-cli` and run:
```
make build
```
This builds statically linked binaries for all supported combinations of operating systems and architectures into the `build` directory.
This command statically builds binaries for all supported combinations of operating systems and architectures into the `build` directory.
To removes all generated files, run:
```
......
# nexus-client
## Introduction
**nexus-client** is the client component of the nexus project, a VDI (Virtual Desktop Infrastructure) written from scratch in Go and based on Linux/KVM + QEMU.
## Components
The full project, **nexus_vdi**, is made of three software components:
1. **nexus-server**: the server program (backend) that runs on a server.
- Exposes a REST API to manage VMs and users
1. **nexus-client**: the client or end-user program to manage VMs, users and templates.
- The client uses REST messages to communicate with `nexus-server`
- The client can be run from anywhere (locally or remotely) as long as it can communicate with `nexus-server`
- Two clients have been developed so far:
- `nexush`: an interactive command line client, similar to a shell. It is the most user-friendly way to interact with `nexus-server`, but it is not suited for scripting.
- `nexus-cli`: a collection of commands particularly suited to scripting and automated operations.
- Both clients offer the same features, functionalities and syntax. A nice touch is that commands support regular expressions allowing many VMs to be created/started/stopped/destroyed/etc. at once.
- Both clients feature an "vmattach" command which lets users interact with their VM's desktop.
- this feature requires `remote-viewer` which is part of the [virt-viewer project](https://gitlab.com/virt-viewer/virt-viewer.git)
1. **nexus-exam**: a minimalistic graphical application used during live exams. It doesn't feature any option and only allows a student to connect to her/his running VM.
To obtain a nexus access, please contact Florent Gluck at florent.gluck@hesge.ch.
## Building nexus-clients and nexus-exam
To build `nexush`, `nexus-cli` and `nexus-exam` read the [following documentation](HOWTO_build.md).
## Obtaining nexus-clients
Precompiled nexus client binaries can be [found here](https://drive.switch.ch/index.php/s/d89cBJBbGvpc4nO).
Two clients are available:
- `nexush` is the most "user-friendly" client; it is the nexus shell
- `nexus-cli` is another client more suited to scripting
Both clients feature the same commands and they are available for multiples operating systems and processor architectures:
| Operating System | Architecture | Clients directory location |
|--- |--- |--- |
| Linux | x86-64/AMD64 | binaries/amd64/linux |
| OSX | x86-64/AMD64 | binaries/amd64/darwin |
| Windows | x86-64/AMD64 | binaries/amd64/windows |
| Linux | ARM64 | binaries/arm64/linux |
| OSX | ARM64 | binaries/arm64/darwin |
| Windows | ARM64 | binaries/arm64/windows |
## Installing nexus-clients' dependency
Both clients require the `remote-viewer` software in order to display remote VM desktops.
### Installing remote-viewer on Linux
On Ubuntu/Debian, `remote-viewer` is part of the `virt-viewer` package which can be installed with:
```
sudo apt-get install virt-viewer
```
### Installing remote-viewer on Windows
On Windows, `remote-viewer` is part of the `virt-viewer` MSI package that can be downloaded here: [https://virt-manager.org/download.html](https://virt-manager.org/download.html).
Once installed, make sure to add the folder where `remote-viewer.exe` is installed to your user's PATH environment variable.
### Installing remote-viewer on Mac OSX
On Mac, `remote-viewer` is part of the `virt-viewer` package from MacPorts that can be installed from here [https://ports.macports.org/port/virt-viewer/](https://ports.macports.org/port/virt-viewer/).
## Overview of nexus' basic concepts
### Templates
- Templates are immutable OS disk images used to create VMs: a VM is an instance of a specific template
- Templates can be `private` or `public`: a private template is only visible to its owner whereas a public template is visible to everyone
- **Important**: templates don't store any hardware configuration (number of CPUs, amount of RAM, network interface, etc.); they only store the disk image, nothing more
### VMs
- A VM is always created from a template
- A VM's hardware (number of CPUs, amount of RAM, network interface, etc.) is completely independant of its disk content
- Access rights to a VM can be finely controlled by its owner and anyone else allowed (see [Access control](#access-control))
### Users
- What users can or cannot do is defined by their capabilities: see [Access control](#access-control) for more information
## Available template images
The table below describes the basic public templates that are currently available. The numbers between parenthesis indicate the year and month of creation (also available in the detailed output of `tpllist -l <template ID>`).
| Template name | Description |
|--- |--- |
| Xubuntu 22.04 (2023.02) + dev env/unpriv user | Xubuntu 22.04 system (Ubuntu with XFCE desktop environment) |
| | + C dev tools (gcc, make, etc.), VScode IDE compiler |
| | + QEMU system hypervisor |
| | `nexus` user (`/home/nexus`) with sudo privileges (pwd `nexus`) |
| | `student` user (`/home/student`) without any privilege (no pwd) |
| Xubuntu 22.04 (2023.02) + dev env/unpriv user/pi-hole | Xubuntu 22.04 system (Ubuntu with XFCE desktop environment) |
| | + C dev tools (gcc, make, etc.), VScode IDE compiler |
| | + QEMU system hypervisor |
| | + Pi-hole domain firewall (see [Domain firewall](#domain-firewall)) |
| | `nexus` user (`/home/nexus`) with sudo privileges (pwd `nexus`) |
| | `student` user (`/home/student`) without any privilege (no pwd) |
| Manjaro 21 xfce (2022.08) | Vanilla Manjaro 21 system with XFCE desktop environment |
| | `nexus` user (`/home/nexus`) with sudo privileges (pwd `nexus`) |
<!--
| Xubuntu 22.04 (2022.08) + dev env | Xubuntu 22.04 system (Ubuntu with XFCE desktop environment) |
| | + C dev tools (gcc, make, etc.), VScode IDE compiler |
| | + QEMU system hypervisor |
| | `nexus` user (`/home/nexus`) with sudo privileges (pwd `nexus`) |
| Debian 11 xfce (2022.08) | Vanilla Debian 11 system with XFCE desktop environment |
| | `nexus` user (`/home/nexus`) with sudo privileges (pwd `nexus`) |
| Ubuntu 22.04 (2022.08) | Vanilla Ubuntu 22.04 system with the GNOME desktop environment |
| | `nexus` user (`/home/nexus`) with sudo privileges (pwd `nexus`) |
-->
## nexush
`nexush` is a **nexus-client** in the form of a single native executable featuring the commands listed below.
Most commands support regular expressions (regex) in order to perform actions on multiple VMs at once.
Regular expressions must conform to the RE2 GO syntax described here [https://github.com/google/re2/wiki/Syntax](https://github.com/google/re2/wiki/Syntax).
`nexush` features commands to manipulate:
- VMs (commands starting with `vm`)
- templates (commands starting with `tpl`)
- users (commands starting with `user`)
Example of execution showing all available commands:
```
Welcome to nexush, the nexus shell.
Type: "help" for help on commands
"quit" or "exit" to quit nexush
nexush> help
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
ls List files in the specified dir or in the current dir if no argument is specified.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
userlist Lists users.
Requires USER_LIST user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
usercreate Creates a user.
Requires USER_CREATE user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
userdel Deletes one or more users.
Requires USER_DESTROY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
usersetcaps Sets a user's capabilities.
Requires USER_SET_CAPS user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
vmlist Lists VMs.
Requires VM_LIST VM access capability or VM_LIST_ANY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
vmcred2pdf Creates a PDF with the credentials required to attach to running VMs.
Requires VM_LIST VM access capability or VM_LIST_ANY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
vmcred2txt Creates a text file with the credentials required to attach to running VMs.
Requires VM_LIST VM access capability or VM_LIST_ANY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
vmstart Starts one or more VMs.
Requires VM_START VM access capability or VM_START_ANY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
vmkill Kills one or more VMs.
Requires VM_STOP VM access capability or VM_STOP_ANY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
vmshutdown Gracefully shutdowns one or more VMs.
Requires VM_STOP VM access capability or VM_STOP_ANY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
vmreboot Gracefully reboots one or more VMs.
Requires VM_REBOOT VM access capability or VM_REBOOT_ANY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
vmattach Attaches to one or more VMs in order to use their desktop environment.
Requires VM_LIST VM access capability or VM_LIST_ANY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
vmcreate Creates one or more VMs.
Requires VM_CREATE user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
vmedit Edits one or more VMs' properties: name, cpus, ram or nic.
Requires VM_EDIT VM access capability or VM_EDIT_ANY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
vmdel Deletes one or more VMs.
Requires VM_DESTROY VM access capability or VM_DESTROY_ANY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
vmaddaccess Adds a user's VM access in one or more VMs.
Requires VM_SET_ACCESS user capability and VM_SET_ACCESS VM access capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
vmdelaccess Removes a user's VM access in one or more VMs.
Requires VM_SET_ACCESS user capability and VM_SET_ACCESS VM access capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
vmexportdir Exports one or more VMs' directory into one or more tar archives.
Requires VM_READFS VM access capability or VM_READFS_ANY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
vmimportdir Copies a local directory (or file) and all its content into one or more VMs.
Requires VM_WRITEFS VM access capability or VM_WRITEFS_ANY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
tpllist Lists available templates.
Requires TPL_LIST or TPL_LIST_ANY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
tplcreate Creates a template from an existing VM.
Requires TPL_CREATE user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
tpledit Edits one or more template's properties: name, access.
Requires TPL_EDIT or TPL_EDIT_ANY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
tpldel Deletes a template.
Requires TPL_DESTROY or TPL_DESTROY_ANY user capability.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
tplexportdisk Exports a template's disk.
Requires TPL_READFS or TPL_READFS_ANY user capability.
```
Note that when attached to a VM's desktop (`vmattach` command), ctrl+F12 toggles between fullscreen/non-fullscreen modes.
## nexus-cli
`nexus-cli` is another **nexus-client** in the form of a single native executable featuring pretty much the exact same commands as `nexush`. Therefore we won't list them here.
## USB redirection
USB redirection allows USB devices plugged in the PC running nexus client to be accessible in the guest OS of the VM running on the server.
When creating a new VM with `vmcreate`, you can specify USB devices that are accessible in the VM. A USB device is specified by two hexadecimal number, a vendor ID (`VID`) and a product ID (`PID`). For instance, the example below creates a VM and allows two USB devices, 067b:2303 (a USB/serial connector) and 0781:5567 (a SanDisk USB key) to be accessible in the VM:
```
vmcreate "usb test" 2 4000 none 067b:2303,0781:5567 fbccb584-9ea6-40f7-926d-dabf3970525e
```
If you wish to forbid all USB devices simply specify "none" instead:
```
vmcreate "usb test" 2 4000 none none fbccb584-9ea6-40f7-926d-dabf3970525e
```
To obtain the vendor ID and product ID of a USB device, run the `lsusb` command on Linux. The output should be similar to the one below, where the sixth column indicates vendor ID and product ID separated by a colon (`:`):
```
Bus 003 Device 026: ID 04d8:0b27 Microchip Technology, Inc. USB2734
Bus 003 Device 003: ID 0b0e:245d GN Netcom Jabra Link 370
Bus 003 Device 009: ID 058f:6362 Alcor Micro Corp. Flash Card Reader/Writer
Bus 003 Device 006: ID 046d:08e3 Logitech, Inc. C505 HD Webcam
```
### Vendor ID and product ID of USB devices of interest
| Device description | VID:PID |
|--- |--- |
| Atmel at91sam SAMBA bootloader | 03eb:6124 |
| Prolific Technology USB/serial | 067b:2303 |
| MyLab2 serial port | 0403:6015 |
| Digilent Analog Discovery 2 | 0403:6014 |
| NXP Semiconductors NXP CMSIS-DAP | 1fc9:001d |
| NXP Semiconductors LPC11U3x CMSIS-DAP v1.0.4 | 1fc9:0132 |
| Saleae Logic Pro 16 | 21a9:1006 |
| Peak USB CAN | 0c72:000c |
| Segger J-Link | 1366:0101 |
| Xilinx KV260 and KR260 JTAG and UART | 0403:6011 |
| Xilinx Nexys Video JTAG | 0403:6010 |
| Xilinx Nexys Video UART | 0403:6001 |
| USBest Technology USB key | 1307:0165 |
| SanDisk Cruzer Blade USB key | 0781:5567 |
## nexush usage examples
Launch `nexush` and log in as user `janedoe@nexus.org` (note that you will be prompted for your password):
```
./nexush janedoe@nexus.org
```
Display available commands:
```
help
```
Display the help for the `vmcreate` command:
```
vmcreate
```
Display information about the currently logged-on user:
```
whoami
```
List all users:
```
userlist .
```
List users matching the "jane" pattern:
```
userlist jane
```
Add new user `lukeskywalker@force.net` with a list of capabilities:
```
useradd lukeskywalker@force.org Luke Skywalker maytheforcebewithyou USER_CREATE USER_DESTROY USER_LIST USER_SET_CAPS VM_CREATE
```
List all listable VMs:
```
vmlist .
```
List all listable VMs with more details ("long output"):
```
vmlist -l .
```
List listable VMs matching the "ubuntu" pattern:
```
vmlist ubuntu
```
List listable VMs matching the "ubuntu" pattern and also the VM with ID `6713ce26-941e-4d95-8e92-6b71d44bf75a`:
```
vmlist ubuntu 6713ce26-941e-4d95-8e92-6b71d44bf75a
```
Start VM `6713ce26-941e-4d95-8e92-6b71d44bf75a`:
```
vmstart 6713ce26-941e-4d95-8e92-6b71d44bf75a
```
Start VMs matching the "exam ISC_433 PCO" pattern:
```
vmstart "exam ISC_433 PCO"
```
Attach to VM `6713ce26-941e-4d95-8e92-6b71d44bf75a` and all VMs matching the pattern "zorglub":
```
vmattach 6713ce26-941e-4d95-8e92-6b71d44bf75a zorglub
```
Shutdown VMs matching the "exam ISC_433 PCO" pattern (for this to work, `qemu-guest-agent` must be running in the VM's guest OS!):
```
vmshutdown "exam ISC_433 PCO"
```
Kill VM `6713ce26-941e-4d95-8e92-6b71d44bf75a`:
```
vmkill 6713ce26-941e-4d95-8e92-6b71d44bf75a
```
Create a VM named "Doom", based on the `fbccb584-9ea6-40f7-926d-dabf3970525e` (Doom) template, with 4 CPUs, 4GB RAM, a network interface with NAT translation, and no USB devices:
```
vmcreate Doom 4 4096 user none fbccb584-9ea6-40f7-926d-dabf3970525e
```
Create 50 VMs with the base name "ISC_433 Exam" based on the `6713ce26-941e-4d95-8e92-6b71d44bf75a` template, with 2 CPUs, 2GB RAM, no network interface, and no USB devices:
```
vmcreate "ISC_433 Exam" 2 2048 none none 6713ce26-941e-4d95-8e92-6b71d44bf75a 50
```
It takes about 30 seconds and 11MB of disk space to create these 50 VMs.
They will have the following names:
```
ISC_433 Exam <1>
ISC_433 Exam <2>
...
ISC_433 Exam <50>
```
Edit VM `6713ce26-941e-4d95-8e92-6b71d44bf75a` by changing its name to "Tagada VM" and no network interface (`none`):
```
vmedit 6713ce26-941e-4d95-8e92-6b71d44bf75a name="Tagada VM" nic=none
```
Edit VMs matching the "PCO lab2" pattern by changing their CPU to 1 core, a network interface with NAT translation (`user`), and adding access to USB devices baba:0007 and 1234:abcd:
```
vmedit "PCO lab2" cpus=1 nic=user usb=baba:0007,1234:abcd
```
Delete VM `6713ce26-941e-4d95-8e92-6b71d44bf75a`:
```
vmdel 6713ce26-941e-4d95-8e92-6b71d44bf75a
```
Delete VMs matching the "exam ISC_433 PCO" pattern:
```
vmdel "exam ISC_433 PCO"
```
Set the VM access for VM `89649fe3-4940-4b77-929e-50903789cd87` with: `VM_LIST` and `VM_DESTROY` for user `student@nexus.org`:
```
vmsetaccess 89649fe3-4940-4b77-929e-50903789cd87 student@nexus.org VM_LIST VM_DESTROY
```
Set VM access for VMs matching the "alpine" pattern with: `VM_START` and `VM_STOP` for user `student@nexus.org`:
```
vmsetaccess alpine student@nexus.org VM_START VM_STOP
```
Remove VM access for `student@nexus.org` from VM `89649fe3-4940-4b77-929e-50903789cd87`:
```
vmdelaccess 89649fe3-4940-4b77-929e-50903789cd87 student@nexus.org
```
Remove VM access for `student@nexus.org` from VMs matching the "lab2" pattern:
```
vmdelaccess lab2 student@nexus.org
```
Generate `exam_vms.pdf` with the credentials required to connect to all running VMs matching "exam prog sys":
```
vmcred2pdf "exam prog sys" output.pdf
```
Extract and download the `/home` directory of all VMs matching "exam prog sys" (each directory is saved in a `.tar.gz` archive named after the VM's ID):
```
vmexportdir "exam prog sys" /home
```
List all available templates:
```
tpllist .
```
List templates matching the "ubuntu" pattern:
```
tpllist ubuntu
```
Create a new `public` template, named "Xubuntu 22.04 + golang toolchain" based on VM `89649fe3-4940-4b77-929e-50903789cd87` (`public` templates are accessible to everyone while `private` templates are only accessible to their creators):
```
tpllist 89649fe3-4940-4b77-929e-50903789cd87 "Xubuntu 22.04 + golang toolchain" public
```
Delete template `3d440a31-17da-423d-8d95-a96b4cecff8b`:
```
tpldel 3d440a31-17da-423d-8d95-a96b4cecff8b
```
Quit `nexush`:
```
quit
```
## nexus-cli usage examples
Given `nexus-cli` offers the same VM, user and template commands as `nexush`, we only show a handful of examples here.
List available commands:
```
./nexus-cli
```
Authentify user `janedoe@nexus.org` and obtain an access token:
```
export NEXUS_TOKEN=`./nexus-cli login janedoe@nexus.org pipomolo`
```
Start VM `6713ce26-941e-4d95-8e92-6b71d44bf75a`:
```
vmstart 6713ce26-941e-4d95-8e92-6b71d44bf75a
```
## nexus-exam
### Running nexus-exam
<!--
`nexus-exam` requires two environment variables:
- `NEXUS_SERVER`: specifies the nexus server to connect to.
- `NEXUS_CERT`: specifies the path to the public certificate required for encrypted communication (TLS) with the nexus server.
Example of variables initialization:
```
export NEXUS_SERVER=10.136.26.127:1077
export NEXUS_CERT=$(pwd)/ca-cert.isc-nexus-prod.pem
```
-->
The purpose of `nexus-exam` is to be used during live exam sessions. Students are provided with laptops configured to boot on dedicated USB keys. These USB keys feature a minimal Linux system that automatically run `nexus-exam` at boot time. 50 such USB keys have been created and are ready to be used.
The only thing that's necessary to use `nexus-exam` is to boot on one of the USB keys mentionned above.
To obtain these USB keys, please contact Florent Gluck at florent.gluck@hesge.ch.
Below is a screenshot of `nexus-exam`'s graphical interface:
![](img/nexus-exam.png)
## Tutorial: creating a live exam with nexush
First and foremost, templates for the most popular distributions are available on HEPIA ISC nexus server. They are described in [Available template images](#available-template-images).
Let's say you want to create an exam for the class "ProgSys". Let's assume 30 students are enrolled in the class.
First, you need to create the VM that will be used by the students during the exam. Typically, this VM will contain the exam environment (compilers, editors, tools, etc.) along the description of the exam, for instance as a PDF on the desktop.
1. First, log-in with your user:
```
./nexush janedoe@nexus.org
```
After entering your password, you should see:
```
janedoe@nexus.org's password:
Welcome to nexush, the nexus shell.
Type: "help" for help on commands
"quit" or "exit" to quit nexush
nexush>
```
1. List available templates and choose the one you wish to use for your exam VM:
```
tpllist .
```
This command displays the templates you can use:
```
Debian 11 xfce (2022.08) | 0accbad1-3865-416f-bac7-a2f80ba7f081 | public
Manjaro 21 xfce (2022.08) | 502c30cb-49ea-4a83-a405-8c9182d9970c | public
Ubuntu 22.04 (2022.08) | 77518795-31e4-4fba-a160-22aa5d603f3e | public
Xubuntu 22.04 (2022.08) + dev env | 0fc5c07a-bc36-4583-934f-0cacf030221b | public
Xubuntu 22.04 (2023.02) + dev env/unpriv user | 8b746cf9-1a9b-4dec-8f3d-4f7479fafd86 | public
Xubuntu 22.04 (2023.02) + dev env/unpriv user/pi-hole | 3d440a31-17da-423d-8d95-a96b4cecff8b | public
```
Let's assume template `0fc5c07a-bc36-4583-934f-0cacf030221b` (Xubuntu 22.04 (2022.08) + dev env), is the one you would like to use.
1. Create the VM based on the chosen template. Let's say you want the VM to be named "Exam ProgSys Oct2022" and you want it to have 2 CPUs, 3GB RAM and access to the Internet (for now):
```
vmcreate "Exam ProgSys Oct2022" 2 3000 user none 0fc5c07a-bc36-4583-934f-0cacf030221b
```
This command displays the name and ID of the created VM(s):
```
Created VM "Exam ProgSys Oct2022" | 148ea20e-9c45-4bd1-a670-f18312d436b8
```
1. Now that the VM is created, you need to start it, connect to it, and configure it to fit your needs. First, start it by starting any VM mathing the following expression (you can also start it by specifying its VM ID):
```
vmstart "exam progsys"
```
This command displays the name of the started VM(s):
```
Started VM "Exam ProgSys Oct2022"
```
1. Attach to the VM in order to configure it to your needs (you can also attach to it by specifying its VM ID):
```
vmattach "exam progsys"
```
This command opens a window showing the VM(s)'s desktop:
![](img/vmattach.jpg)
1. Configure the VM to suit your needs, by:
- upgrading the system with `sudo apt-get update && apt-get upgrade` (not required)
- installing applications required for the exam, e.g. compilers, tools, editors, etc.
Once done, you must shutdown the VM.
<!--
- installing the QEMU Guest Agent with `sudo apt-get install qemu-guest-agent` (so you will be able to use the `vmshutdown` command)
-->
1. Add the exam' specific material. All materials (questions, code, etc.) can be copied from your local machine to the VM with `vmimportdir`. Here, we copy the "exam" directory into the VM's Desktop (`/home/nexus/Desktop`):
```
vmimportdir "exam progsys" exam /home/nexus/Desktop
```
The command displays the directory was copied successfully:
```
Successfully copied "exam" into "/home/nexus/Desktop" in VM "Exam ProgSys Oct2022"
```
1. Now that the VM is ready for the exam, create a template from it. The template must be `private` as we don't want anyone else to access it. Let's choose "Exam ProgSys Oct2022" as the template name (template creation takes several minutes, the larger the VM, the longer). The first argument is the VM ID (as displayed when the VM was created earlier):
```
tplcreate 148ea20e-9c45-4bd1-a670-f18312d436b8 "Exam ProgSys Oct2022" private
```
This command displays details about the newly created template:
```
{
"id": "0fb0b1f2-c72c-416e-961a-6bb802da89bb",
"name": "Exam ProgSys Oct2022",
"owner": "florent.gluck@hesge.ch",
"access": "private"
"creationTime": "2022-10-25T16:42:17+01:00"
}
```
1. You can now create the VMs for your 30 students using your new template (ID `0fb0b1f2-c72c-416e-961a-6bb802da89bb`). Let's say the base name for the 30 VMs to create is "Live Exam ProgSys Oct2022". You want the VMs to have: 2 CPUs, 3GB RAM and no network interface to prevent any fraud. Create a CSV file, say `students.csv` with the names of your 30 students, one per line. Then, create the 30 VMs with:
```
vmcreate "Live Exam ProgSys Oct2022" 2 3000 none none 0fb0b1f2-c72c-416e-961a-6bb802da89bb students.csv
```
This command displays each VM created:
```
Created VM "Live Exam ProgSys Oct2022 <Alia Friedman>" | 74d8b83d-f59e-4129-bf68-af574968cf48
Created VM "Live Exam ProgSys Oct2022 <Aria Doyle>" | f3047faa-2f15-4f47-b79f-9acc19751b6c
Created VM "Live Exam ProgSys Oct2022 <Avah Coffey>" | 3ebd56a2-2c1e-416c-9847-f80ee3efa1c1
Created VM "Live Exam ProgSys Oct2022 <Briley Brady>" | 245fc5b2-b192-4b41-80be-2d39b5a2cef2
Created VM "Live Exam ProgSys Oct2022 <Brooklyn Sweeney>" | a9bafd7e-28f0-4f37-8b90-5e3c82d4bbc5
Created VM "Live Exam ProgSys Oct2022 <Cornelius Simmons>" | 40edb2b1-b4e9-4928-9dea-316ed834bf07
Created VM "Live Exam ProgSys Oct2022 <Donovan Heath>" | 8ae5c9cd-16f3-4e02-a940-e4209a6d7010
Created VM "Live Exam ProgSys Oct2022 <Ella Webster>" | 7d16f88f-afb1-4633-a646-57a9c87411d5
...
```
1. The day of the exam, you'll have to start the 30 VMs and generate a PDF with the credentials required to connect to each VM. To start the 30 VMs, run:
```
vmstart "live exam progsys"
```
This command displays each VM started:
```
Started VM "Live Exam ProgSys Oct2022 <Alia Friedman>"
Started VM "Live Exam ProgSys Oct2022 <Aria Doyle>"
Started VM "Live Exam ProgSys Oct2022 <Avah Coffey>"
Started VM "Live Exam ProgSys Oct2022 <Briley Brady>"
Started VM "Live Exam ProgSys Oct2022 <Brooklyn Sweeney>"
Started VM "Live Exam ProgSys Oct2022 <Cornelius Simmons>"
Started VM "Live Exam ProgSys Oct2022 <Donovan Heath>"
Started VM "Live Exam ProgSys Oct2022 <Ella Webster>"
...
```
1. Finally, to produce the PDF file, `creds.pdf`, with all credentials required to attach to each VM, run:
```
vmcred2pdf "live exam progsys" creds.pdf
```
This command displays that file was written successfully:
```
creds.pdf written successfully.
```
Here is what the PDF looks like:
![](img/vmcred2pdf.png)
1. You can now print the PDF above, cut each line and give each student the strip of paper for their VM. Once a student has completed their exam, they shutdown their VM and give you the strip of paper back. Note that you can also shutdown the VM yourself with `nexus-cli vmshutdown` (provided the guest OS is running `qemu-guest-agent`). You can also force a VM to be stopped with `nexus-cli vmkill` although it's not recommended as it might corrupt the VM's filesystem.
1. To correct the students' exams, simply download the relevant files to your computer using `vmexportdir`. As an example, the command below extracts and downloads the `/home/nexus/Desktop/exam` directory of all VMs matching "Live Exam ProgSys" (each directory is saved in a `.tar.gz` archive named after the VM's name):
```
vmexportdir "live exam progsys" /home/nexus/Desktop/exam
```
This command displays each exported file tree:
```
Successfully exported /home/nexus/Desktop/exam from VM "Live Exam ProgSys Oct2022 <Alia Friedman>" into Live Exam ProgSys Oct2022 <Alia Friedman>.tar.gz
Successfully exported /home/nexus/Desktop/exam from VM "Live Exam ProgSys Oct2022 <Aria Doyle>" into Live Exam ProgSys Oct2022 <Aria Doyle>.tar.gz
Successfully exported /home/nexus/Desktop/exam from VM "Live Exam ProgSys Oct2022 <Avah Coffey>" into Live Exam ProgSys Oct2022 <Avah Coffey>.tar.gz
Successfully exported /home/nexus/Desktop/exam from VM "Live Exam ProgSys Oct2022 <Briley Brady>" into Live Exam ProgSys Oct2022 <Briley Brady>.tar.gz
Successfully exported /home/nexus/Desktop/exam from VM "Live Exam ProgSys Oct2022 <Brooklyn Sweeney>" into Live Exam ProgSys Oct2022 <Brooklyn Sweeney>.tar.gz
Successfully exported /home/nexus/Desktop/exam from VM "Live Exam ProgSys Oct2022 <Cornelius Simmons>" into Live Exam ProgSys Oct2022 <Cornelius Simmons>.tar.gz
Successfully exported /home/nexus/Desktop/exam from VM "Live Exam ProgSys Oct2022 <Donovan Heath>" into Live Exam ProgSys Oct2022 <Donovan Heath>.tar.gz
Successfully exported /home/nexus/Desktop/exam from VM "Live Exam ProgSys Oct2022 <Ella Webster>" into Live Exam ProgSys Oct2022 <Ella Webster>.tar.gz
...
```
## Advanced use: configuring nexush and nexus-cli
Because communication between nexus client and nexus server is encrypted, a public certificate is required. Both clients, `nexush` and `nexus-cli`, embed the necessary public certificate to communicate with the server. By default, they are also configured to communicate with the production nexus-server available at ISC.
Both clients can be configured to communicate with any nexus server. ISC has two nexus serveurs, one for production use and one for development. The corresponding public certificates can be found in the `certificates` directory on this git repository.
Here are the ip addresses, ports and certificates to use ISC's production and development nexus servers:
| Server | IP | Port | Certificate |
|--- |--- |--- |--- |
| production | 10.136.26.127 | 1077 | ca-cert.isc-nexus-prod.pem |
| development | 10.136.26.125 | 1077 | ca-cert.isc-nexus-dev.pem |
Nexus clients use two environment variables to specify which nexus server to use and on which port, and which public certificate to use:
| Variable | Description |
|--- |--- |
| NEXUS_SERVER | server to use, using the syntax: `ip:port` |
| NEXUS_CERT | location (path) to the public certificate to use |
On Linux and Mac OSX, a simple and effective way is to store these variables in a `.env` file that is sourced before running the clients.
Here is an example of `.env.nexus` file configured to use the production ISC server:
```
export NEXUS_SERVER=10.136.26.127:1077
export NEXUS_CERT=$(pwd)/ca-cert.isc-nexus-prod.pem
```
Then, source it and run your client of choice:
```
source .env.nexus
./nexush
```
## Access control
Access control is implemented through capabilities.
Capabilities define what users can or cannot do. They are divided into two categories:
- **User capabilities**: define user access control; these are stored in the user metadata
- **VM access capabilities**: define access to VMs; these are stored in the VM metadata
### User capabilities
The various operations a user can or cannot do are defined by her/his capabilities.
The table below lists all potential capabilities associated to a user:
| Capability | Description |
|--- |--- |
| USER_CREATE | Can create a user |
| USER_DESTROY | Can destroy a user |
| USER_SET_CAPS | Can change a user's capabilities |
| USER_LIST | Can list all users |
| VM_CREATE | Can create a VM |
| VM_DESTROY_ANY | Can destoy **ANY** VM |
| VM_EDIT_ANY | Can edit **ANY** VM |
| VM_START_ANY | Can start **ANY** VM |
| VM_STOP_ANY | Can kill/shutdown **ANY** VM |
| VM_REBOOT_ANY | Can Reboot **ANY** VM |
| VM_LIST_ANY | Can list **ANY** VM |
| VM_READFS_ANY | Can export files from **ANY** VM |
| VM_WRITEFS_ANY | Can import files into **ANY** VM |
| VM_SET_ACCESS | Can change (edit or delete) a VM's access |
| TPL_CREATE | Can create a template |
| TPL_EDIT | Can edit a template |
| TPL_EDIT_ANY | Can edit **ANY** template |
| TPL_DESTROY | Can destroy a template |
| TPL_DESTROY_ANY | Can destroy **ANY** template |
| TPL_LIST | Can list public or owned templates |
| TPL_LIST_ANY | Can list **ANY** template |
| TPL_READFS | Can export files from a public or owned templates |
| TPL_READFS_ANY | Can export files from **ANY** template |
### VM access capabilities
What a user can or cannot do **with a VM** is defined by the capabilities stored in the VM for this very user.
The table below lists all potential capabilities granted to a user for a given VM.
These capabilities are called "VM access capabilities":
| Capability | Description |
|--- |--- |
| VM_SET_ACCESS | User can add/change access to the VM |
| | VM_SET_ACCESS **must also be present** in the user's capabilities! |
| VM_DESTROY | User can destroy the VM |
| VM_EDIT | User can edit the VM |
| VM_START | User can start the VM |
| VM_STOP | User can kill/shutdown the VM |
| VM_REBOOT | User can reboot the VM |
| VM_LIST | User can list or attach to the VM |
| VM_READFS | User can export files from the VM |
| VM_WRITEFS | User can import files into the VM |
### IMPORTANT
- When a user creates a VM, she/he is **automatically granted all VM access capabilities**.
- No other users is granted any access to the created VM. However, the VM owner can add any access type to any users they like.
## Domain firewall
Some templates come with a domain firewall already installed: [Pi-hole](https://pi-hole.net/).
Pi-hole is a tool that lets you configure which domains are accessible and which are not. It can use whitelists or blacklists to define what's allowed or not and it's highly configurable through either a web interface or the command line.
To configure Pi-hole in the VM:
1. Log on with the `nexus` user as you'll need root privileges
1. Set the password to access the web interface by running the following in a terminal:
```
pihole -a -p
```
1. Log on Pi-hole's interface by going to `http://pi.hole` in a browser
1. In the configuration, all domains are blocked except for the ones that are whitelisted; consequently, you must configure the domains you want to allow (you can also disable domain filtering entirely)
1. Once done, the settings will be persistent
The Pi-hole installation in the template(s) already come with domain rules to allow/forbid the three scenarios below:
- [Cyberlearn](https://cyberlearn.hes-so.ch)
- [Gitedu](https://gitedu.hesge.ch)
- Docker Hub (to allow `docker pull/run` from docker CLI)
## FAQ
### [1] What is QEMU Guest Agent?
QEMU Guest Agent is a service (a *daemon* in the UNIX terminology) that is meant to run inside a VM's guest OS. Its purpose is to interact with the hypervisor so that the hypervisor can read the state of the guest OS, send commands (e.g. shutdown, reset, etc.), read files, etc. Communications between hypervisor and QEMU Guest Agent is done through the QEMU Guest Agent Protocol.
Certain nexus features require QEMU Guest Agent to run in the VM's guest OS. This is the case of the `vmshutdown` command which gracefully shutdowns a VM. This command won't work if QEMU Guest Agent is not running in the VM's guest OS.
All base OS VM templates provided in nexus feature QEMU Guest Agent, so users don't need to worry about it.
On a Ubuntu/Debian system, the `qemu-guest-agent` service can be installed with:
```
sudo apt-get install qemu-guest-agent
```
### [2] How to automatically change the display resolution when the window's dimensions change?
Some desktop environments automatically take care of this out of the box. Gnome in Ubuntu does it automatically, but XFCE doesn't do it for instance.
Below we desribe what to do to solve this issue. The idea is to execute a script that runs indefinitely. The scripts' purpose is to monitor the display output and whenever a change of resolution is detected, it adjusts the display to the newly detected resolution.
1. As root, create the bash script below and save it into `/usr/local/bin/update-virt-display`:
```bash
#!/bin/bash
# Indefinitely wait for a screen resolution change and when one happens, update the desktop size accordingly.
xev -root -event randr | \
grep --line-buffered 'subtype XRROutputChangeNotifyEvent' | \
while read vars ; do \
xrandr --output "$(xrandr | awk '/ connected/{print $1; exit; }')" --auto
done
```
1. As root, make the script executable with:
```
chmod +x /usr/local/bin/update-virt-display
```
1. Then, for each user you want to support, create a `.xprofile` file in the user's home directory with the following content:
```
/usr/local/bin/update-virt-display &
```
File moved
<!--
This document describes how each VM OS image is created and the post-install steps that have been undertaken.
-->
# Common to all distribs
- username: `nexus`
......
File moved
File moved
File moved
......@@ -7,21 +7,13 @@ import (
"strings"
"encoding/json"
"nexus-client/cmd"
t "nexus-common/template"
u "nexus-client/utils"
g "nexus-client/globals"
"github.com/google/uuid"
"github.com/go-resty/resty/v2"
)
// Converts a Template structure into a pretty string.
func (tpl *Template)String() string {
output, err := json.MarshalIndent(tpl, "", " ")
if err != nil {
return err.Error()
}
return string(output)
}
func printUsage(c cmd.Command, action string) {
for _, desc := range c.GetDesc() {
u.PrintlnErr(desc)
......@@ -81,7 +73,12 @@ func printFilteredTemplates(c cmd.Command, args []string, route string) int {
if foundLongOutputFlag >= 0 {
for _, template := range templates {
u.Println(template.String())
str, err := template.String()
if err != nil {
u.PrintlnErr("Failed decoding template "+template.ID.String()+" to string. Skipped.")
} else {
u.Println(str)
}
}
} else {
// Compute the length of the longest name and access (used for padding columns)
......@@ -122,7 +119,7 @@ func printFilteredTemplates(c cmd.Command, args []string, route string) int {
// Regular expression examples:
// "." -> matches everything
// "bla" -> matches any template name containing "bla"
func getFilteredTemplates(route string, patterns []string) ([]Template, error) {
func getFilteredTemplates(route string, patterns []string) ([]t.TemplateSerialized, error) {
if len(patterns) < 1 {
return nil, errors.New("At least one ID or regex must be specified")
}
......@@ -147,7 +144,7 @@ func getFilteredTemplates(route string, patterns []string) ([]Template, error) {
return nil, err
}
templatesList := []Template{}
templatesList := []t.TemplateSerialized{}
if resp.IsSuccess() {
templates, err := getTemplates(resp)
......@@ -186,8 +183,8 @@ func getFilteredTemplates(route string, patterns []string) ([]Template, error) {
}
// Retrieves all templates (no filtering).
func getTemplates(resp *resty.Response) ([]Template, error) {
templates := []Template{}
func getTemplates(resp *resty.Response) ([]t.TemplateSerialized, error) {
templates := []t.TemplateSerialized{}
if err := json.Unmarshal(resp.Body(), &templates); err != nil {
return nil, err
}
......
......@@ -26,11 +26,11 @@ func (cmd *Create)PrintUsage() {
u.PrintlnErr(desc)
}
u.PrintlnErr("―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――")
u.PrintlnErr("USAGE: "+cmd.GetName()+" ID name access")
u.PrintlnErr("USAGE: "+cmd.GetName()+" name access vmID")
u.PrintlnErr("―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――")
u.PrintlnErr("vmID ID of the VM used to create the template.")
u.PrintlnErr("name Name of the template to create.")
u.PrintlnErr("access Access type, either \"public\" or \"private\"")
u.PrintlnErr("access Access type, either \"public\" or \"private\".")
u.PrintlnErr("vmID ID of the VM used to create the template.")
}
func (cmd *Create)Run(args []string) int {
......@@ -40,12 +40,12 @@ func (cmd *Create)Run(args []string) int {
return 1
}
vmID, err := uuid.Parse(args[0])
name := args[0]
access := args[1]
vmID, err := uuid.Parse(args[2])
if err != nil {
u.PrintlnErr(err)
}
name := args[1]
access := args[2]
resp, err := cmd.makeRequestForID(vmID, name, access)
if err != nil {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment