stuve-it-backend/Readme.md

402 lines
16 KiB
Markdown
Raw Normal View History

2023-10-26 20:34:59 +00:00
# StuVe IT Tools Backend
## Übersicht
Als Backend für die StuVe IT Tools wird [Pocketbase](https://pocketbase.io)
verwendet. Pocketbase ist ein self-hosted Backend-as-a-Service, der auf SQLite basiert.
2023-10-26 20:34:59 +00:00
## Was ist Pocketbase?
Implementiert ist Pocketbase in Golang und kann dort auch einfach als
Library eingebunden werden und so [erweitert](https://pocketbase.io/docs/go-overview/) werden.
Dies wurde in diesem Projekt auch gemacht, um die Authentifizierung
um eine LDAP Authentifizierung zu erweitern.
Aus diesem Grund handelt es sich bei diesem Projekt nicht um
einen Fork von Pocketbase, sondern um eine Library, die Pocketbase
erweitert.
Pocketbase selbst bietet folgende Features:
- Datenbank
- Als Datenbank verwendet Pocketbase SQLite
- Authentifizierung
- Pocketbase bietet sogenannte "Auth-Collections" an, die eine
Authentifizierung über E-Mail und Passwort ermöglichen.
- Es ist allerdings möglich dieses Mechanismus zu erweitern was in
diesem Projekt auch gemacht wurde. (siehe unten)
- File Storage
- Pocketbase bietet einen File Storage an, der allerdings nur
Dateien bis 5B unterstützt.
- Achtung: Per Default sind alle Dateien öffentlich zugänglich.
- E-Mail Versand (limitiert aber in Golang erweiterbar)
- Pocketbase sendet per Default nur System E-Mails, zb Passwort
vergessen.
- Über Golang ist es allerdings möglich den E-Mailversand zu
erweitern. Dies ist in **Planung**.
- Realtime Events (Websockets)
- Pocketbase bietet einen Realtime Event Service an, der über
Websockets funktioniert. Dabei können auf alle Datenbank Events (Insert,
Update, Delete) reagiert werden.
- JavaScript SDK
- Pocketbase bietet ein JavaScript SDK an, das alle Features von
Pocketbase unterstützt.
2023-11-20 15:32:32 +00:00
## Admin UI
Pocketbase bietet eine Admin UI an, die unter `https://<pocketbase-url>/_/` erreichbar ist.
Der Login hierzu ist im SysPass unter *Pocketbase* zu finden.
In der Admin UI können Tabellen erstellt, bearbeitet und gelöscht werden.
Außerdem können die API Rules bearbeitet werden, die festlegen, welche
Funktionen für die einzelnen Tabellen und User erlaubt sind.
2023-10-26 20:34:59 +00:00
## Entwickeln
2023-11-20 15:32:32 +00:00
```bash
git clone https://git.stuve.uni-ulm.de/stuve-it/stuve-it-backend.git
cd stuve-it-backend
go run main/main.go serve # --debug=0 for no debug output
2023-11-20 15:32:32 +00:00
```
2023-10-26 20:34:59 +00:00
## Installation
2023-11-20 15:32:32 +00:00
Das Projekt kann mittels Docker installiert werden.
Durch die Gitlab CI/CD Pipeline wird bei jedem Push auf `main` ein neues Docker
Image erstellt. Dieses muss dann nur noch auf dem Server deployt werden.
2023-10-26 20:34:59 +00:00
## Projekt Struktur
Die einzelnen custom go Packages sind weiter unten beschrieben.
```
├── Dockefile # Dockerfile für die Entwicklung
├── .dockerignore # Dateien die nicht in den Docker Container kopiert werden sollen
├── .gitignore # Dateien die nicht in Git gepusht werden sollen
├── go.mod # Go Module Datei (Go's Package Manager)
├── main # Main Package (App Entry Point)
│ └── main.go # Main Funktion
├── logger # Custom Logger Package
│ └── main.go # Logger Funktionen
├── ldapSync # LDAP Sync Package
│ ├── main.go # LDAP Sync Entry Point
│ ├── db.go # Datenbank Funktionen (Insert Users, Groups, ...)
│ ├── models.go # Structs für LDAP User und Group
│ ├── tables.go # Erstellt die benötigten Tabellen in der Datenbank (Users, Groups, Logs)
│ └── ldapSync.go # Sync Funktionen (Sync Users, Groups, ...)
├── ldapApi # LDAP API Package
│ └── main.go # Api Route
└── qrApi # QR API Package
└── main.go # Api Route
2023-10-26 20:34:59 +00:00
```
## Custom Packages
Damit Pocketbase mit der StuVe IT Tools Infrastruktur funktioniert,
wurden einige Packages erstellt, die Pocketbase erweitern.
### Logger
Das Logger Package ist ein custom Logger, der die Log-Nachrichten
farblich in die Konsole schreibt.
Diese Package ist sehr minimal gehalten und bietet nur die
Funktionen `Success`, `Info` und `Error` an.
#### Beispiel
```go
package main
import "git.stuve.uni-ulm.de/stuve-it/stuve-it-backend/logger"
func main() {
logger.LogInfoF("Info Message")
logger.LogErrorF("Warn Message")
logger.LogErrorF("Error Message")
}
```
### QR API
Das QR API Package ist ein einfaches Package, das eine API Route
zum Generieren von QR-Codes in SVG anbietet.
#### API Route
Das Package bietet die Route `GET /api/qr/v1` an, welche die folgenden
Parameter als query string entgegennimmt:
| Parameter | Datentyp | Beschreibung |
|-------------------|-------------|------------------------------------------------------------------------------------------------|
| `data` | string | Der Text, der im QR-Code codiert werden soll (**required**) |
| `ecc` | string-enum | Der Error Correction Level des QR-Codes (`L`, `M` - default, `Q`, `H`) |
| `scale` | int | Der Scale des QR-Codes (default `1`) |
| `border` | int | Der Border des QR-Codes (default `1`), eine Border Uni ist die Größe von einem QR-Code 'pixel' |
| `color` | hex-string | Die Farbe des QR-Codes (default `#000000`) |
| `colorBackground` | hex-string | Die Hintergrundfarbe des QR-Codes (default `#FFFFFF`) |
#### Beispiel
```bash
curl -X GET https://it.stuve.uni-ulm.de/api/qr/v1?data=stuve.uni-ulm.de
```
2023-10-26 20:34:59 +00:00
### LDAP API
Im LDAP API Package sind zwei API Routen implementiert:
- LDAP Login: `POST /api/ldap/login`
- LDAP Search: `GET /api/ldap/search`
#### LDAP Login
Dieses Package implementiert eine LDAP Authentifizierung, die Pocketbase um eine LDAP Authentifizierung erweitert.
Das Package bietet die Route `POST /api/ldap/login` an, welche die folgenden
Parameter als json entgegennimmt:
| Parameter | Datentyp | Beschreibung |
|------------|----------|-------------------------------------------------------|
| `username` | string | Der Benutzername des LDAP Users (`cn`) (**required**) |
| `password` | string | Das Passwort des LDAP Users (**required**) |
##### Konfiguration
Das Package benötigt folgende ENV Variablen:
- `LDAP_URL`: LDAP Server URL (e.g. `ldap://ldap.stuve.uni-ulm.de`)
##### Mechanismus
Das Passwort wird mit dem LDAP Server abgeglichen und nach einer
erfolgreichen Authentifizierung ein Token und das ldap_user Modell
zurückgegeben. Die `memberOf` Beziehungen werden dabei automatisch geladen.
Das Passwort wird nicht in der Datenbank gespeichert.
Diese Response ist identisch mit der standard Pocketbase Authentifizierung (z.B. AuthWithPassword).
##### Beispiel
```bash
curl -X POST https://it.stuve.uni-ulm.de/api/ldap/login -d '{"username": "vorname.nachname", "password": "*******"}'
```
#### LDAP Search
Dieses Package implementiert eine LDAP Suche, die Pocketbase um eine LDAP Suche erweitert.
Damit kann per HTTP Request die LDAP Datenbank durchsucht werden.
Das Package bietet die Route `GET /api/ldap/search` an, welche die folgenden
Parameter als json entgegennimmt:
| Parameter | Datentyp | Beschreibung |
|--------------|----------|-------------------------------------------------------------------------------------------------------------|
| `baseDN` | string | Die Base DN, in der gesucht werden soll (**required**) |
| `filter` | string | Der Filter, nach dem gesucht werden soll (**required**) |
| `attributes` | []string | Die Attribute, die zurückgegeben werden sollen, bei einem leeren Array werden alle Attribute zurückgegeben. |
##### Konfiguration
Das Package benötigt folgende ENV Variablen:
- `LDAP_URL`: LDAP Server URL (e.g. `ldap://ldap.stuve.uni-ulm.de`)
- `LDAP_BIND_DN`: LDAP Bind DN (zum Lesen der LDAP Datenbank, admin user)
- `LDAP_ADMIN_GROUP_DN`: LDAP Admin Group DN (Gruppe, die Admin Rechte hat)
##### Mechanismus
Die Route führt eine LDAP Suche durch und gibt die gefundenen LDAP
Objekte zurück. Dabei wird die Suche mit dem `LDAP_BIND_DN` durchgeführt.
Es wird überprüft, ob der User der das GET Request schickt in der `LDAP_ADMIN_GROUP_DN` Gruppe ist.
##### Beispiel
```bash
curl -X GET https://it.stuve.uni-ulm.de/api/ldap/search -d '{"baseDN": "ou=useraccounts,ou=user,dc=stuve,dc=uni-ulm,dc=de", "filter": "(cn=vorname.nachname)"}'
```
2024-03-27 17:18:43 +00:00
Als return wir ein JSON Objekt nach folgendem Schema zurückgegeben:
```json
{
"Entries": [
{
"DN": "CN=vorname.nachname,OU=UserAccounts,OU=User,DC=stuve,DC=uni-ulm,DC=de",
"Attributes": [
{
"Name": "cn",
"Values": [
"vorname.nachname"
],
"ByteValues": [
"xxxxxxxxxxxxxxx"
]
}
]
}
],
"Referrals": [],
"Controls": []
}
```
Json Schemata:
```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"Entries": {
"type": "array",
"items": {
"type": "object",
"properties": {
"DN": {
"type": "string"
},
"Attributes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"Name": {
"type": "string"
},
"Values": {
"type": "array",
"items": {
"type": "string"
}
},
"ByteValues": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["Name", "Values", "ByteValues"]
}
}
},
"required": ["DN", "Attributes"]
}
},
"Referrals": {
"type": "array",
"items": {}
},
"Controls": {
"type": "array",
"items": {}
}
},
"required": ["Entries", "Referrals", "Controls"]
}
```
2023-10-26 20:34:59 +00:00
### LDAP Sync
Dieses Package ist das umfangreichste Package und synchronisiert
die LDAP Datenbank mit der Pocketbase Datenbank.
Dabei werden alle LDAP User und Gruppen in die Pocketbase Datenbank
kopiert.
Dieses Package erfordert, dass alle Gruppen und User das Attribut `objectGUID` haben. Dies ist in der Regel bei Windows
ADs der Fall.
#### LDAP Attribute
Die folgenden LDAP Attribute werden in der Pocketbase Datenbank gespeichert.
##### User
| Attribut | Pocketbase Name | Beschreibung |
|----------------|--------------------------------------------|-------------------------------------------------------------------|
| objectGUID | id | Eindeutige ID des Users (nur die ersten 15 Zeichen werden genutzt |
| givenName | givenName | Vorname des Users |
| sn | sn | Nachname des Users |
| mail | email | E-Mail des Users |
| memberOf | memberOf (in Pocketbase eine SQL Relation) | Gruppenzugehörigkeit des Users |
| accountExpires | accountExpires (in Pocketbase UTC) | Account Ablaufdatum |
| dn | dn | Distinguished Name des Users |
| cn | cn & username | Common Name des Users |
##### Group
| Attribut | Pocketbase Name | Beschreibung |
|-------------|--------------------------------------------|--------------------------------------------------------------------|
| objectGUID | id | Eindeutige ID der Gruppe (nur die ersten 15 Zeichen werden genutzt |
| cn | cn | Common Name der Gruppe |
| dn | dn | Distinguished Name der Gruppe |
| description | description | Beschreibung der Gruppe |
| memberOf | memberOf (in Pocketbase eine SQL Relation) | Gruppenzugehörigkeit der Gruppe |
2023-10-26 20:34:59 +00:00
#### Konfiguration
Das Package benötigt folgende ENV Variablen:
- `LDAP_URL`: LDAP Server URL (e.g. `ldap://ldap.stuve.uni-ulm.de`)
- `LDAP_BIND_DN`: LDAP Bind DN (zum Lesen der LDAP Datenbank, admin user)
- `LDAP_BIND_PASSWORD`: LDAP Bind Password (das Passwort des admin users)
- `LDAP_USER_BASE_DN`: LDAP User Base DN (hier werden alle User gesucht,
e.g. `ou=useraccounts,ou=user,dc=stuve,dc=uni-ulm,dc=de`)
- `LDAP_USER_FILTER`: LDAP User Filter (e.g. `(|(objectCategory=person)(objectClass=user))`)
- `LDAP_ADMIN_GROUP_DN`: LDAP Admin Group DN (Gruppe, die Admin Rechte hat)
2023-10-26 20:34:59 +00:00
- `LDAP_GROUP_BASE_DN`: LDAP Group Base DN (hier werden alle Gruppen gesucht,
e.g. `ou=groups,ou=user,dc=stuve,dc=uni-ulm,dc=de`)
- `LDAP_GROUP_FILTER`: LDAP Group Filter (e.g. `(objectClass=group)`)
- `LDAP_SUNC_SCHEDULE`: LDAP Sync Schedule (e.g. `*/1 * * * *` für minütliches Syncen)
(siehe [Cron](https://en.wikipedia.org/wiki/Cron))
#### Tabellen
Das Package erstellt folgende Tabellen in der Pocketbase Datenbank:
- `ldap_users`: Alle LDAP User ([auth-Collection](https://pocketbase.io/docs/collections/#auth-collection))
- `ldap_groups`: Alle LDAP Gruppen
- `ldap_sync_logs`: Alle LDAP Sync Logs (wann wurde was synchronisiert)
Die Tabellen werden automatisch erstellt, wenn das Programm gestartet wird und sie noch nicht existieren.
#### Sync
Das Package synchronisiert die LDAP Datenbank mit der Pocketbase Datenbank.
Dabei werden alle LDAP User und Gruppen in die Pocketbase Datenbank
kopiert. Es werden `memberOf` ldap Attribute verwendet, um die
Gruppenzugehörigkeit zu bestimmen und in SQL Relationen umzuwandeln.
Beim ersten synchronisieren kann es sein, dass eine `memberOf` Gruppe
noch nicht existiert. In diesem Fall wird die Beziehung erst beim
nächsten Sync erstellt. Falls eine `memberOf` Gruppe nicht gefunden wird,
wird dies in der Konsole geloggt.
Für jede Synchronisation wird ein Log-in der `ldap_sync_logs` Tabelle
2023-10-26 20:34:59 +00:00
erstellt.
Sowohl für die ldap_users als auch für die ldap_groups Tabelle wird
unter den API Rules das bearbeiten und löschen deaktiviert, da diese
Tabellen nur synchronisiert werden und nicht manuell bearbeitet werden
sollen.
Dadruch können sie nur über das LDAP Sync Package (und die Admin UI) bearbeitet werden.
#### User Sync
Damit man sich später auch als Nutzer anmelden kann, werden die
User in einer `auth` Collection gespeichert. Allerdings werden
natürlich nicht die LDAP Passwörter synchronisiert.
Aus diesem Grund muss auch jede Auth-Methode unter Options im Admin UI
für diese Collection deaktiviert werden (Username, E-Mail, OAuth2).
Mehr dazu unter dem LDAP Login Package.
2023-11-20 15:32:32 +00:00
#### DB Util
In der `db.go` Datei sind alle Datenbank Funktionen implementiert.
Hier gibt es Methoden um User oder Groups zu finden, die dabei automatisch
die Beziehungen zu anderen Tabellen laden (`memberOf`).