Skip to content
Open
7 changes: 3 additions & 4 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
Copyright 2022 TU Delft & Valentijn van de Beek

Copyright <YEAR> <COPYRIGHT HOLDER>
Copyright 2022 TU Delft
Copyright 2022-2024 Valentijn van de Beek

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
Expand All @@ -27,4 +26,4 @@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 changes: 8 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mkfile_dir := $(shell dirname $(mkfile_path))
# or to the ip address of the control server when ~~testing~~ running in production.
# This will be put in the hosts file.
export CONTROL_SERVER_IP ?= 192.168.2.76
export FIRST_MAC_ADDRESS ?= 52:54:00:08:5e:49

lint_fix:
goimports -local baas -w **/*.go
Expand All @@ -14,16 +15,19 @@ lint:
goimports -local baas -w **/*.go
golangci-lint run

management_os: management_initramfs management_kernel
.PHONY: management_os
management_os: management_initramfs

management_initramfs:
@$(mkfile_dir)/management_os/build/build_management_initramfs.sh

management_initramfs: control_server/static/initramfs

control_server_docker:
@docker-compose -f $(mkfile_dir)/docker-compose.yml up --build

.PHONY: control_server
control_server:
cd $(mkfile_dir) && sudo env GO111MODULE=on go run ./control_server
cd $(mkfile_dir) && sudo env GO111MODULE=on GITHUB_SECRET=${GITHUB_SECRET} go run ./control_server

.PHONY: setup_control_server
setup_control_server:
@$(mkfile_dir)/utils/setup_control_server.sh ${FIRST_MAC_ADDRESS}
52 changes: 31 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@

# BAAS

Baremetal As A Service, or abbreviated to BAAS is a project done for the TU Delft to facilitate operating systems
research on high-powered machines, by scheduling the access researches have to these machines. This system makes sure
each researcher can have full access to the machines in their timeslot, being able to load their own (custom) kernel and have
access to all hardware. BAAS makes sure the system is reset a well-known state after every job, to make sure these custom kernels
have not messed up the system enough to make further research on them impossible.

Disclaimer: this system is custom-built for the needs of the TU Delft. It is open source, and written to be extensible,
but it is unlikely that it will completely fit your needs without changes. We are open to pull requests,
but we might not implement suggestions ourselves which are outside the scope of the requirements for the TU Delft.
Baremetal As A Service, or abbreviated to BAAS is a project done for
the TU Delft to facilitate operating systems research on high-powered
machines, by scheduling the access researches have to these
machines. This system makes sure each researcher can have full access
to the machines in their timeslot, being able to load their own
(custom) kernel and have access to all hardware. BAAS makes sure the
system is reset a well-known state after every job, to make sure these
custom kernels have not messed up the system enough to make further
research on them impossible.

Disclaimer: this system is custom-built for the needs of the TU
Delft. It is open source, and written to be extensible, but it is
unlikely that it will completely fit your needs without changes. We
are open to pull requests, but we might not implement suggestions
ourselves which are outside the scope of the requirements for the TU
Delft.

# Documentation

Some documentation about the systems, and building these systems is provided [here](https://baas-project.github.io/baas/). In addition, you can generate a website with inline documentation by running `godoc` and going to [this url](http://localhost:6060/pkg/github.com/baas-project/baas/).
Some documentation about the systems, and building these systems is
provided [here](https://baas-project.github.io/baas/). In addition,
you can generate a website with inline documentation by running
`godoc` and going to [thisurl](http://localhost:6060/pkg/github.com/baas-project/baas/).

# Install

Expand All @@ -26,7 +36,7 @@ Some documentation about the systems, and building these systems is provided [he

## Installation of the virtual machine
This software works on a client a server-model, where there is a
central control server which offers the management OS to one or multiple
central control server which offers the management OS to one or multiple
clients. These are two entirely different systems and hence both
testing as well as developing must be done on two separate machines.

Expand All @@ -41,8 +51,8 @@ new network, select NAT, set the name as BAASNetwork and set "Forward
To" as the network card you typically use (in my case wlan0). Press on
finish.

> :warning: If you have problems with connecting to the server,
> double check if there is not a firewall running in the background.
> :warning: If you have problems with connecting to the server,
> double check if there is not a firewall running in the background.
Run the following command, after running it, you should be able to
boot the virtual machine with the proper network settings.

Expand All @@ -51,8 +61,8 @@ virt-install --pxe --prompt --memory 2048 --name baas --disk size=30
--boot uefi,network,hd --network network=BAASNetwork --os-variant generic
```

Finally generate the management operating system which is run on the
client machine.
Finally generate the management operating system which is run on the
client machine.

```sh
make management_initramfs
Expand All @@ -61,11 +71,11 @@ make management_initramfs
### Control server
In `virt-manager` go to view and select Details, press on the light
bulb and find the menu item called NIC. From there copy the MAC
address and change the value in control_server/main.go to this IP
address. You can then run `make control_server` to run the control
server and reboot the virtual machine. If all is well, it should now
boot into the management operating system.
address and change `FIRST_MAC_ADDRESS` in the Makefile to this
value. You can then run `make control_server` to run the control
server. Then you can run `make setup_control_server` to create an
administrator user, a first disk image and add the VM to BAAS. If all
is well, it should now boot into the management operating system.

# License

// TODO
[3-Clause BSD][https://github.com/baas-project/baas/blob/master/LICENSE]
2 changes: 1 addition & 1 deletion control_server/api/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func getHandler(machineStore database.Store, staticDir string, diskpath string)
AllowedHeaders: []string{"Authorization", "Set-Cookie"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
AllowCredentials: true,
Debug: true,
Debug: false,
})

return c.Handler(r)
Expand Down
53 changes: 27 additions & 26 deletions docs/control_server/REST API.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ In general of all of the resources look like the following:

Different resources may be nested in groups of two arbitrarily deep into other resources, for example, `/machine/[mac]/disk/[uuid]/file/[name]`.

Some endpoints may require a user to be logging in, as indicated by the permissions field in the documentation below, which means that the `session-name` cookie must be set to the right value. This can be done by simply [logging in](logging_in.md), copying the relevant cookie value and using it in your requests. For example, using cURL you want to prefix your commands with: `--cookie "session-name=[some base64 string]"`.
Some endpoints may require a user to be logging in, as indicated by the permissions field in the documentation below, which means that the `session-name` cookie must be set to the right value. This can be done by simply [logging in](logging_in.md), copying the relevant cookie value and using it in your requests. For example, using cURL you want to prefix your commands with: `--cookie "session-name=[some base64 string]"`. Checks can be skipped, for now, by setting a `Type: System` header in your HTTP request.

To send a request you must set the Origin Header due to the [Cross-Origin Resource Sharing][https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS] protections of modern browsers. At the moment, only `http://localhost:9090` is supported as a value.

## Endpoint compendium
In this section an overview is given of every single on the defined endpoints together with an example on how to call it, what parameters it takes and what it returns. This section is divided in the same way as the resources defined above.
Expand All @@ -53,10 +54,10 @@ Allows a user to get information about a specific machine which is identified by
{
"Name": "Machine 1",
"Architecture": "X86_64",
"Managed": true,
"Managed": true,
"MacAddress": [{
"Address": "00:11:22:33:44:55:66"
}]
"Address": "00:11:22:33:44:55:66"
}]
}
```

Expand All @@ -71,19 +72,19 @@ Receives information about every currently registered machine.
**Example response:**<br>
```json
[{
"Name": "Machine 1",
"Name": "Machine 1",
"Architecture": "x86_64",
"Managed": true,
"Managed": true,
"MacAddress": [{
"Address": "00:11:22:33:44:55:66"
"Address": "00:11:22:33:44:55:66"
}]
},
{
"Name": "Machine 2",
"Name": "Machine 2",
"Architecture": "x86_64",
"Managed": false,
"Managed": false,
"MacAddress": [{
"Address": "42:DE:AD:BE:EF:42"
"Address": "42:DE:AD:BE:EF:42"
}]
}]
```
Expand All @@ -105,16 +106,16 @@ the machine.
**Example body:**<br>
```json
{
"Name": "Hello World",
"Architecture": "x86_64",
"Managed": true,
"MacAddress": [{
"Address": "52:54:00:d9:71:15",
"MachineModelID": 12
}]
"Name": "Hello World",
"Architecture": "x86_64",
"Managed": true,
"MacAddress": [{
"Address": "52:54:00:d9:71:15",
"MachineModelID": 12
}]
}
```
**Example curl command:** `curl -X POST localhost:4848/machine -H 'Content-Type: application/json' -d '{"name": "Test", "Architecture": "x86_64", "Managed": true, "MacAddress": {"Address": "52:54:00:d9:71:12"}1}'`
**Example curl command:** `curl -X POST localhost:4848/machine -H 'Content-Type: application/json' -d '{"name": "Test", "Architecture": "x86_64", "Managed": true, "MacAddress": {"Address": "52:54:00:d9:71:12"}}'`

#### Update machine
Change the information of a machine, this also used to create a machine.
Expand All @@ -132,12 +133,12 @@ Change the information of a machine, this also used to create a machine.
**Example body:**<br>
```json
{
"Name": "Hello World",
"Architecture": "x86_64",
"Managed": true,
"MacAddress": [{
"Mac": "52:54:00:d9:71:15",
}]
"Name": "Hello World",
"Architecture": "x86_64",
"Managed": true,
"MacAddress": [{
"Mac": "52:54:00:d9:71:15",
}]
}
```
**Example curl command:** `curl -X PUT localhost:4848/machine -H 'Content-Type: application/json' -d '{"name": "Test", "Architecture": "x86_64", "Managed": true, "MacAddress": {"Address": "52:54:00:d9:71:12"}}'`
Expand Down Expand Up @@ -339,7 +340,7 @@ Creates a new image entity and file.
- *Type:* BAAS image type, one of: base, system, temporal and temporary<br>
- *Versioned:* Boolean value indicating that it is a versioned or a
checksum-based image<br>

- *Username:* Username of the user that you want to create the image for<br>
**Response:**
- *Name:* Human-readable name of the image.<br>
- *Versions:* A list of objects with a Version attribute containing the version number.<br>
Expand All @@ -351,7 +352,7 @@ Creates a new image entity and file.
- *Checksum:* Checksum in case of a non-versioned image.<br>

**Permissions:** User in question or administrator<br>
**Example curl request:** `curl -X POST "localhost:4848/user/ValentijnvdBeek/image" -H 'Content-Type: application/json' --cookie "session-name=$SECRET" -d '{"Name": "Fedora Research", "DiskCompressionStrategy": "none", "ImageFileType": "raw", "Type": "system"}'`<br>
**Example curl request:** `curl -X POST "localhost:4848/user/ValentijnvdBeek/image" -H 'Content-Type: application/json' --cookie "session-name=$SECRET" -d '{"Name": "Fedora Research", "DiskCompressionStrategy": "none", "ImageFileType": "raw", "Type": "system","username":"ValentijnvdBeek"}'`<br>
**Example Response:**
```json
{
Expand Down
7 changes: 4 additions & 3 deletions docs/control_server/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ possible.
## Documentation index
1. [Running the Server](running_baas_control_server.md)
2. [REST API](REST API.md)
3. [Logging In](logging_in.md)

## Overview of how the typical interaction works
When the control server is run the server will open a SQL database and
Expand All @@ -31,11 +32,11 @@ image that should be booted and any information about images such as
compression algorithm.

!!! Danger
The implementation of the system message is incredibly
The implementation of the system message is incredibly
simple and allows for the complete bypassing of all security
mechanisms. Please do not deploy the BAAS project on a safety
critical system until this mechanism is replaced with a more
secure implementation.
critical system until this mechanism is replaced with a more
secure implementation.

Each request sent to the system is checked whether it is a system
message and hence is provided with a specific header, whether a user
Expand Down
4 changes: 4 additions & 0 deletions docs/control_server/logging_in.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ server on future requests in order to authenticate yourself. There is
functionally no difference between logging and registering since the
user will be made on first login.

In order to make use of the Github OAuth system, you need to register
an application and set the right values in `api/login.go`. You can
pass the secret as `GITHUB_SECRET`

At the moment is not possible to register multiple OAuth sources to
one account. Each login as seen as unique and distinct even with
shared data. Keep in mind that if you use the same username for
Expand Down
27 changes: 20 additions & 7 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Normally, you would use a virtual machine to create a client machine and run the

!!! warning "Firewalls can interfere with VM networks."
If you have problems with connecting to the server, double check if there is not a firewall running in the background.
Run the following command, after running it, you should be able to boot the virtual machine with the proper network settings.
Run the following command, after running it, you should be able to boot the virtual machine with the proper network settings.

```sh
virt-install --pxe --prompt --memory 2048 --name baas --disk size=30
Expand All @@ -58,22 +58,35 @@ make management_initramfs
```

### Starting the control server
In `virt-manager` go to view and select Details, press on the light bulb and find the menu item called NIC. From there copy the MAC address and change the value in `control_server/main.go` to this MAC address. You can then run `make control_server` to run the control server.
In `virt-manager` go to view and select Details, press on the light bulb and find the menu item called NIC. From there copy the MAC address and change `FIRST_MAC_ADDRESS` in the Makefile to this value. You can then run `make control_server` to run the control server. Then you can run `make setup_control_server` to create an administrator user, a first disk image and add the VM to BAAS. If all is well, it should now boot into the management operating system.

### Scheduling the first boot
At boot the server will add the machine and hence the only thing left to do is ensuring that the system actually has images that it can boot. First create a user on the system, followed by the creation of an initial image and the downloading this image to disk. It is assumed that you have the `curl` and `jq` utilities installed and are running on a UNIX system.

```sh
curl -X POST "localhost:4848/user" -H 'Content-Type: application/json' -d '{"name": "USER", "email": "EMAIL", "role": "user"}'
UUID=$(curl -X POST "localhost:4848/user/USER/image" -H 'Content-Type: application/json' -d '{"name": "Test image", "DiskUUID": "/dev/sda"}' | jq .UUID | sed 's/\"//g')
curl "localhost:4848/image/${UUID}/latest" --output /tmp/image.img
# Set a preamble for each of the cURL requests. In particular:
# - Content-Type -- Type of request data we are giving
# - Origin -- Were the request originates from, at the moment we only accept localhost (needed for CORS)
# - Type -- Allows a request to bypass session user checking
HEADERS=$(cat <<EOF
Content-Type: application/json
Origin: http://localhost:9090
Type: system
EOF
)
URL="localhost:4848"

curl -X POST "$URL/user" -H "$HEADERS" -d '{"name": "USER", "email": "EMAIL", "role": "user", "username": "sampleuser"}'
UUID=$(curl -X POST "$URL:4848/user/USER/image" -d d '{"name": "USER", "email": "EMAIL", "role": "user", "username": "sampleuser"}' | jq .UUID)
curl "$URI/image/${UUID}/latest" --output /tmp/image.img
```

Running these commands creates an initial user called USER and a testing image which is downloaded on disk. This image can be modified in any arbitrary way or can be replaced with another file entirely. After creating the image the modified can be uploaded and scheduled for booting by running the following commands:

```sh
VERSION=$(curl -X POST "localhost:4848/image/${UUID}" -H "Content-Type: multipart/form-data" -F "file=@/tmp/image.img" | awk '{print $4}')
curl -X POST "localhost:4848/machine/[your MAC address]/boot" -H 'Content-Type: application/json' -d "{\"Version\": ${VERSION}, \"ImageUUID\": \"${UUID}\", \"update\": false}"
MAC="some-mac-address"
VERSION=$(curl -X POST "$URI/image/${UUID}" -H "$HEADERS" -H "Content-Type: multipart/form-data" -F "file=@/tmp/image.img" | awk '{print $4}')
curl -X POST "$URL/machine/$MAC/boot" -H "$HEADERS" -d "{\"Version\": ${VERSION}, \"ImageUUID\": \"${UUID}\", \"update\": false}"
```

### Running the virtual machine
Expand Down
2 changes: 1 addition & 1 deletion management_os/build/build_management_initramfs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ source $SCRIPT_PATH/../../utils/container.sh
# Generate the image directory
generateImage $SCRIPT_PATH

CONTROL_SERVER_IP="$(hostname -I | awk '{print $1}')"
CONTROL_SERVER_IP="$(ip a | grep -F "inet " | awk '{print $2}' | sed -n 2p | rev | cut -b 4- | rev)"

cat > "$SCRIPT_PATH/hosts" << EOF
# Put the ip address of the control server here so the management
Expand Down
Loading