Skip to content

Commit

Permalink
Merge branch 'master' into better-selector
Browse files Browse the repository at this point in the history
  • Loading branch information
dgdavid committed Feb 14, 2024
2 parents 96da343 + 9b6654b commit 6ffe93b
Show file tree
Hide file tree
Showing 20 changed files with 615 additions and 543 deletions.
173 changes: 173 additions & 0 deletions doc/new_architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Agama's 2024 architecture

This document describes the proposal for the new Agama architecture. The reasons for introducing
these changes are recorded in [a discussion in Agama's repository][drop-cockpit].

[drop-cockpit]: https://github.com/openSUSE/agama/discussions/1000

But before describing how the architecture should look, let's quickly look at the current status.

## The current architecture

At this point, Agama is composed of four high-level components:

* **Agama service**: implements the logic to perform the installation. It is the core component of
Agama and it offers a D-Bus interface. Actually, it is composed of two services: `rubygem-agama` and
`agama-dbus-server`.

* **Web user interface (`cockpit-agama`)**: a web-based interface that plays the role of a GUI when
using Agama live.

* **Command Line Interface (`agama-cli`)**: it allows to interact with Agama core and drives the
auto-installation process.

* **Auto-installation (`autoinstallation`)**: it is composed by a Systemd service (`agama-auto`) and
a script that relies on `agama-cli`.

In addition to those components, we need to consider Cockpit, which plays a vital role:

* It makes communication between the web UI and the D-Bus services possible.
* It makes the web UI code available to the browser.
* It takes care of authenticating the user when connecting remotely. Again, it is only relative to
the web UI.

```mermaid
flowchart LR
subgraph Clients
Browser
CLI
auto
end
subgraph Cockpit
UI["Web UI"]
end
subgraph Agama Service
Rust[Agama Rust]
Ruby[Agama Ruby]
end
Browser <---> UI
UI <--D-Bus--> Rust
UI <--D-Bus--> Ruby
CLI <--D-Bus--> Rust
CLI <--D-Bus--> Ruby
Rust <--D-Bus---> Ruby
auto --> CLI
```

## The new architecture

The proposed architecture is not that different from the current one, but it tries to meet these
goals:

* Drop our dependency on Cockpit.
* Implement a higher-level API to be consumed by the clients, replacing D-Bus for client-server
communication. Agama will still use D-Bus for IPC between the Rust and Ruby components.

### Components

With those goals in mind, we are considering the following components:

* **Agama core (old `agama-dbus-server`)**: implements the installation logic. It relies heavily on
the Agama YaST service.

* **Agama YaST service (old `rubygem-agama`)**: it is written in Ruby and has direct access to YaST
libraries. Complex parts, like storage and software handling, are implemented in this component.

* **HTTP and WebSocket API**: implements the API the clients should use to communicate with Agama.
Under the hood, it still uses D-Bus for communication between Agama core and Agama YaST.

* **Web user interface (old `cockpit-agama`)**: Agama's graphical user interface. The web server
makes this React application available to the browsers.

* **Command Line Interface (`agama-cli`)**: it allows interaction with Agama and drives the
auto-installation process. With the new architecture, connecting through the network might be
possible without SSH.

* **Auto-installation (`autoinstallation`)**: as in the current architecture, it is composed by
a Systemd service (`agama-auto`) and a script that relies on `agama-cli`.

The following diagram could be better, but it represents the main components and their interactions.

```mermaid
flowchart LR
subgraph Clients
Browser
CLI
auto
end
subgraph Agama Core
subgraph Web["Web Server"]
direction TB
UI["Web UI"]
API["HTTP/WS API"]
WS["WebSocket"]
end
Web <--"Channel" --> Rust
end
Rust <-- "D-Bus" --> YaST["Agama YaST"]
Browser --> UI
Browser --> API
Browser <---> WS
CLI --> API
CLI <---> WS
auto --> CLI
```

### The web-based API

The new web-based API is divided into two different parts:

* **HTTP/JSON API**: allows clients to execute actions or query Agama. For instance, it could get
the list of available products, request a new storage proposal or start the installation. About the
approach, something REST-like is the most suitable. Switching to GraphQL or gRPC do not seem to be
needed in our case (todo: write why).

* **WebSocket**: Agama will use WebSockets to notify clients about any relevant event: progress,
configuration changes, etc. The event's format is not defined yet, but a JSON event containing the
`type` and the `payload/details` should be enough[^topics].

[^topics]: Ideally, the clients should be able to subscribe to the topics they are interested in.
But that feature can wait.

### Encryption

In the case of a remote installation, the communication between the clients and the server must be
encrypted. Connecting to port 80 (HTTP) should redirect the client to port 443 (HTTPS).

About the certificate, Agama will use a self-signed certificate unless the user injects its own
certificate (through a kernel command line option).

NOTE: under discussion.

### Authentication

The HTTP interface should allow authentication specifying a user and password that will be checked
against PAM. It is not clear yet, but we might need to check whether the logged user has permissions
(making sure it is `root` or through Polkit).

On successful authentication, the server generates a [JSON Web Token][jwt] that the client will
include in the subsequent requests. The web client stores the token in an HTTP-only
cookie[^http-only] and the CLI uses a file with restricted permissions.

[^http-only] HTTP-only cookies cannot be accessed byt client-side JavaScript.

#### Skipping the authentication

When using Agama locally in the installation media, it would be unpleasant to ask for a
user/password. For that reason, there must be a mechanism to skip the authentication step. Agama
Live could run a special service that generates a valid token and injects such a token into the
server, the CLI and the web browser.

## Links

* https://bugzilla.suse.com/show_bug.cgi?id=1219688
* https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html

[http-auth]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
[jwt]: https://jwt.io
4 changes: 4 additions & 0 deletions products.d/microos-desktop.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ description: 'A distribution for the desktop offering automatic updates and
# Do not manually change any translations! See README.md for more details.
translations:
description:
es: Una distribución para escritorio que ofrece actualizaciones automáticas y
reversión sobre los fundamentos de openSUSE MicroOS. Incluye Podman
Container Runtime y permite administrar software usando Gnome Software o
KDE Discover.
fr: Une distribution pour le bureau offrant des mises à jour automatiques et un
rétablissement au dessus des fondations d'openSUSE MicroOS. Inclut Podman
Container Runtime et permet de gérer les logiciels en utilisant Gnome
Expand Down
5 changes: 5 additions & 0 deletions products.d/microos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ description: 'A quick, small distribution designed to host container workloads
# Do not manually change any translations! See README.md for more details.
translations:
description:
es: Una distribución pequeña y rápida diseñada para alojar cargas de trabajo de
contenedores con administración y parches automatizados. openSUSE MicroOS
proporciona actualizaciones transaccionales (atómicas) en un sistema de
archivos raíz btrfs de solo lectura. Como distribución de lanzamiento
continuo, el software siempre está actualizado.
fr: Une petite distribution rapide conçue pour héberger des charges de travail
de conteneurs avec une administration et des correctifs automatisés.
openSUSE MicroOS fournit des mises à jour transactionnelles (atomiques)
Expand Down
10 changes: 5 additions & 5 deletions service/lib/agama/storage/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -293,12 +293,12 @@ def check_multipath
mods = `lsmod`.lines.grep(/dm_multipath/)
logger.warn("dm_multipath modules is not loaded") if mods.empty?

conf_file = File.exist?(MULTIPATH_CONFIG)
if conf_file
finder = File.readlines(MULTIPATH_CONFIG).grep(/find_multipaths\s+smart/)
logger.warn("find_multipaths is not set to smart value") if finder.empty?
binary = system("which multipath")
if binary
conf = `multipath -t`.lines.grep(/find_multipaths "smart"/)
logger.warn("multipath: find_multipaths is not set to 'smart'") if conf.empty?
else
logger.warn("#{MULTIPATH_CONFIG} does not exist")
logger.warn("multipath is not installed.")
end
end
end
Expand Down
6 changes: 3 additions & 3 deletions web/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,15 @@ bots:
# when you start a new project, use the latest release, and update it from time to time
test/common:
flock Makefile sh -ec '\
git fetch --depth=1 https://github.com/cockpit-project/cockpit.git 267; \
git fetch --depth=1 https://github.com/cockpit-project/cockpit.git 309; \
git checkout --force FETCH_HEAD -- test/common; \
git reset test/common'

# checkout Cockpit's PF/React/build library; again this has no API stability guarantee, so check out a stable tag
# TODO: replace the commit with the tag 267 once it is released, which includes cockpit.js as a ES6 module in lib/.
# TODO: replace the commit with the tag 309 once it is released, which includes cockpit.js as a ES6 module in lib/.
$(LIB_TEST):
flock Makefile sh -ec '\
git fetch --depth=1 https://github.com/cockpit-project/cockpit.git 267; \
git fetch --depth=1 https://github.com/cockpit-project/cockpit.git 309; \
git checkout --force FETCH_HEAD -- ../pkg/lib; \
git reset -- ../pkg/lib'
mv ../pkg/lib src/ && rmdir ../pkg
Expand Down
9 changes: 7 additions & 2 deletions web/package/cockpit-agama.changes
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
-------------------------------------------------------------------
Mon Feb 12 11:53:29 UTC 2024 - Imobach Gonzalez Sosa <[email protected]>

- Update cockpit.js to version 309 (gh#openSUSE/agama#1038).

-------------------------------------------------------------------
Mon Jan 29 14:34:37 UTC 2024 - Knut Anderssen <[email protected]>

- Partly replacing the NetworkManager client by the agama one
- Partly replacing the NetworkManager client by the Agama one
(gh#openSUSE/agama#1006).

-------------------------------------------------------------------
Fri Jan 19 09:34:26 UTC 2024 - Nagu <[email protected]>

- Storage UI: show mount point selector only when the user can change it.
(gh#openSUSE/agama#1007)

-------------------------------------------------------------------
Thu Jan 18 08:33:52 UTC 2024 - Ancor Gonzalez Sosa <[email protected]>

Expand Down
44 changes: 20 additions & 24 deletions web/po/cs.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-01-28 02:07+0000\n"
"POT-Creation-Date: 2024-02-07 02:04+0000\n"
"PO-Revision-Date: 2023-12-31 20:39+0000\n"
"Last-Translator: Ladislav Slezák <[email protected]>\n"
"Language-Team: Czech <https://l10n.opensuse.org/projects/agama/agama-web/cs/"
Expand Down Expand Up @@ -377,8 +377,8 @@ msgid ""
"can be set in the %s page."
msgstr ""

#. TRANSLATORS: page title
#. TRANSLATORS: page section
#. TRANSLATORS: page title
#: src/components/l10n/InstallerLocaleSwitcher.jsx:56
#: src/components/l10n/L10nPage.jsx:384
#: src/components/overview/L10nSection.jsx:52
Expand Down Expand Up @@ -593,31 +593,33 @@ msgstr ""
msgid "At least one address must be provided for selected mode"
msgstr ""

#: src/components/network/IpSettingsForm.jsx:131
#. TRANSLATORS: %s is replaced by the iSCSI target node name
#: src/components/network/IpSettingsForm.jsx:133
#: src/components/storage/iscsi/EditNodeForm.jsx:50
#, c-format
msgid "Edit %s connection"
msgid "Edit %s"
msgstr ""

#. TRANSLATORS: network connection mode (automatic via DHCP or manual with static IP)
#: src/components/network/IpSettingsForm.jsx:133
#: src/components/network/IpSettingsForm.jsx:138
#: src/components/network/IpSettingsForm.jsx:140
#: src/components/network/IpSettingsForm.jsx:136
#: src/components/network/IpSettingsForm.jsx:141
#: src/components/network/IpSettingsForm.jsx:143
msgid "Mode"
msgstr ""

#: src/components/network/IpSettingsForm.jsx:144
#: src/components/network/IpSettingsForm.jsx:147
msgid "Automatic (DHCP)"
msgstr ""

#. TRANSLATORS: manual network configuration mode with a static IP address
#: src/components/network/IpSettingsForm.jsx:146
#: src/components/network/IpSettingsForm.jsx:149
#: src/components/storage/iscsi/NodeStartupOptions.js:25
msgid "Manual"
msgstr ""

#. TRANSLATORS: network gateway configuration
#: src/components/network/IpSettingsForm.jsx:161
#: src/components/network/IpSettingsForm.jsx:164
#: src/components/network/IpSettingsForm.jsx:167
msgid "Gateway"
msgstr ""

Expand Down Expand Up @@ -649,18 +651,18 @@ msgstr ""

#. TRANSLATORS: page section title
#. TRANSLATORS: page title
#: src/components/network/NetworkPage.jsx:170
#: src/components/overview/NetworkSection.jsx:102
#: src/components/network/NetworkPage.jsx:169
#: src/components/overview/NetworkSection.jsx:83
msgid "Network"
msgstr ""

#. TRANSLATORS: page section
#: src/components/network/NetworkPage.jsx:172
#: src/components/network/NetworkPage.jsx:171
msgid "Wired networks"
msgstr ""

#. TRANSLATORS: page section
#: src/components/network/NetworkPage.jsx:177
#: src/components/network/NetworkPage.jsx:176
msgid "WiFi networks"
msgstr ""

Expand Down Expand Up @@ -757,13 +759,13 @@ msgstr ""
msgid "The system will use %s as its default language."
msgstr ""

#: src/components/overview/NetworkSection.jsx:78
#: src/components/overview/NetworkSection.jsx:59
msgid "No network connections detected"
msgstr ""

#. TRANSLATORS: header for the list of active network connections,
#. %d is replaced by the number of active connections
#: src/components/overview/NetworkSection.jsx:87
#: src/components/overview/NetworkSection.jsx:68
#, c-format
msgid "%d connection set:"
msgid_plural "%d connections set:"
Expand All @@ -782,8 +784,8 @@ msgstr ""
msgid "%s (registered)"
msgstr ""

#. TRANSLATORS: page section
#. TRANSLATORS: page title
#. TRANSLATORS: page section
#: src/components/overview/ProductSection.jsx:71
#: src/components/product/ProductPage.jsx:435
msgid "Product"
Expand All @@ -798,8 +800,8 @@ msgstr ""
msgid "Refresh the repositories"
msgstr ""

#. TRANSLATORS: page title
#. TRANSLATORS: page section
#. TRANSLATORS: page title
#: src/components/overview/SoftwareSection.jsx:143
#: src/components/software/SoftwarePage.jsx:81
msgid "Software"
Expand Down Expand Up @@ -1734,12 +1736,6 @@ msgstr ""
msgid "Incorrect port"
msgstr ""

#. TRANSLATORS: %s is replaced by the iSCSI target node name
#: src/components/storage/iscsi/EditNodeForm.jsx:50
#, c-format
msgid "Edit %s"
msgstr ""

#: src/components/storage/iscsi/InitiatorForm.jsx:42
msgid "Edit iSCSI Initiator"
msgstr ""
Expand Down
Loading

0 comments on commit 6ffe93b

Please sign in to comment.