added docker compose and ci/cd
This commit is contained in:
parent
b6157c67ae
commit
bcb143ca76
|
@ -0,0 +1,5 @@
|
|||
.env.local
|
||||
.gitignore
|
||||
.gitlab-ci.yml
|
||||
docker-compose.yml
|
||||
Readme.md
|
|
@ -0,0 +1,15 @@
|
|||
stages:
|
||||
- build
|
||||
|
||||
build-container:
|
||||
stage: build
|
||||
image:
|
||||
name: gcr.io/kaniko-project/executor:v1.9.0-debug
|
||||
entrypoint: [ "" ]
|
||||
script:
|
||||
- /kaniko/executor
|
||||
--context "${CI_PROJECT_DIR}"
|
||||
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
|
||||
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"
|
||||
only:
|
||||
- main
|
|
@ -0,0 +1,40 @@
|
|||
# Start from the official Go image to create a build artifact.
|
||||
# This is the first stage of a multi-stage build.
|
||||
FROM golang:1.19 as builder
|
||||
|
||||
# Set the working directory inside the container.
|
||||
WORKDIR /build
|
||||
|
||||
# Copy go.mod and go.sum to download dependencies.
|
||||
COPY go.mod .
|
||||
|
||||
# Download Go modules (dependencies).
|
||||
RUN go mod download
|
||||
|
||||
# Copy the rest of the source code.
|
||||
COPY . .
|
||||
|
||||
# https://stackoverflow.com/questions/36279253/go-compiled-binary-wont-run-in-an-alpine-docker-container-on-ubuntu-host
|
||||
ENV CGO_ENABLED=0
|
||||
|
||||
# Build the Go app as a static binary.
|
||||
# You might need to add tags or other build arguments depending on your application.
|
||||
RUN go build -o pocketbase main/main.go
|
||||
|
||||
# Start from a smaller image to make the final image smaller.
|
||||
FROM alpine:latest
|
||||
|
||||
# Set the working directory inside the container.
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the statically-linked binary from the builder stage.
|
||||
COPY --from=builder /build/pocketbase .
|
||||
|
||||
# Expose port 8090 to the outside world.
|
||||
EXPOSE 8090
|
||||
|
||||
# Update Path
|
||||
ENV PATH="/app:${PATH}"
|
||||
|
||||
# Command to run the executable.
|
||||
CMD ["./pocketbase", "serve", "--http=0.0.0.0:8090", "--dir=/pb_data"]
|
39
Readme.md
39
Readme.md
|
@ -42,13 +42,28 @@ Pocketbase selbst bietet folgende Features:
|
|||
- Pocketbase bietet ein JavaScript SDK an, das alle Features von
|
||||
Pocketbase unterstützt.
|
||||
|
||||
## 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.
|
||||
|
||||
## Entwickeln
|
||||
|
||||
todo
|
||||
```bash
|
||||
git clone ...
|
||||
cd backend
|
||||
go run main.go serve # --debug=0 for no debug output
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
todo
|
||||
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.
|
||||
|
||||
## Projekt Struktur
|
||||
|
||||
|
@ -152,6 +167,12 @@ für diese Collection deaktiviert werden (Username, E-Mail, OAuth2).
|
|||
|
||||
Mehr dazu unter dem LDAP Login Package.
|
||||
|
||||
#### 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`).
|
||||
|
||||
### LDAP Login
|
||||
|
||||
Dieses Package ist für die Authentifizierung zuständig.
|
||||
|
@ -168,7 +189,7 @@ Das Package benötigt folgende ENV Variablen:
|
|||
|
||||
Dieses Package für der Api die folgende Route hinzu:
|
||||
|
||||
`GET /api/ldap/login`
|
||||
`POST /api/ldap/login`
|
||||
|
||||
Diese Route nimmt die Parameter `username` und `password` als json Body entgegen:
|
||||
|
||||
|
@ -179,11 +200,9 @@ Diese Route nimmt die Parameter `username` und `password` als json Body entgegen
|
|||
}
|
||||
```
|
||||
|
||||
Dabei wird das Passwort mit dem LDAP Server abgeglichen und falls
|
||||
erfolgreich ein Token und das ldap_user Modell zurückgegeben.
|
||||
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.
|
||||
|
||||
#### Token Refresh
|
||||
|
||||
todo
|
||||
Diese Response ist identisch mit der standard Pocketbase Authentifizierung (z.B. AuthWithPassword).
|
|
@ -0,0 +1,33 @@
|
|||
services:
|
||||
pocketbase:
|
||||
image: gitlab.uni-ulm.de:5050/stuve-it/it-tools/backend
|
||||
#command:
|
||||
# - "--debug"
|
||||
container_name: stuve_it_backend
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- pb_data:/pb_data
|
||||
ports:
|
||||
- 8090:8090
|
||||
healthcheck:
|
||||
test: wget --no-verbose --tries=1 --spider http://localhost:8090/api/health || exit 1
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
environment:
|
||||
|
||||
LDAP_URL: "ldap://dc.stuve.uni-ulm.de"
|
||||
|
||||
LDAP_BIND_DN: "cn=ldapsync,ou=systemaccounts,ou=user,dc=stuve,dc=uni-ulm,dc=de"
|
||||
LDAP_BIND_PASSWORD: "************"
|
||||
|
||||
LDAP_BASE_DN: "ou=useraccounts,ou=user,dc=stuve,dc=uni-ulm,dc=de"
|
||||
LDAP_USER_FILTER: "(|(objectCategory=person)(objectClass=user))"
|
||||
|
||||
LDAP_GROUP_FILTER: "(objectClass=group)"
|
||||
LDAP_GROUP_BASE_DN: "ou=groups,ou=user,dc=stuve,dc=uni-ulm,dc=de"
|
||||
|
||||
LDAP_SYNC_SCHEDULE: "*/1 * * * *"
|
||||
|
||||
volumes:
|
||||
pb_data:
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/pocketbase/pocketbase/apis"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"gitlab.uni-ulm.de/stuve-it/it-tools/backend/ldapSync"
|
||||
"gitlab.uni-ulm.de/stuve-it/it-tools/backend/logger"
|
||||
"os"
|
||||
)
|
||||
|
||||
|
@ -27,11 +28,16 @@ import (
|
|||
// if the user is authenticated successfully the endpoint returns and apis.RecordAuthResponse
|
||||
func InitLDAPLogin(app *pocketbase.PocketBase, e *core.ServeEvent) error {
|
||||
|
||||
e.Router.GET("/api/ldap/login", func(c echo.Context) error {
|
||||
// add endpoint to app
|
||||
logger.LogInfoF("Adding LDAP Login Endpoint")
|
||||
|
||||
e.Router.POST("/api/ldap/login", func(c echo.Context) error {
|
||||
|
||||
logger.LogInfoF("LDAP Login")
|
||||
|
||||
// step 1: get data from request
|
||||
data := struct {
|
||||
CN string `json:"cn" form:"cn"`
|
||||
Username string `json:"username" form:"username"`
|
||||
Password string `json:"password" form:"password"`
|
||||
}{}
|
||||
if err := c.Bind(&data); err != nil {
|
||||
|
@ -39,7 +45,7 @@ func InitLDAPLogin(app *pocketbase.PocketBase, e *core.ServeEvent) error {
|
|||
}
|
||||
|
||||
// step 2: get ldap user by cn from ldapUsers table
|
||||
record, err := ldapSync.GetLdapUserByCN(app, data.CN)
|
||||
record, err := ldapSync.GetLdapUserByCN(app, data.Username)
|
||||
|
||||
// if user does not exist in ldapUsers table return error
|
||||
if err != nil {
|
||||
|
@ -57,7 +63,7 @@ func InitLDAPLogin(app *pocketbase.PocketBase, e *core.ServeEvent) error {
|
|||
defer conn.Close()
|
||||
|
||||
// step 4: bind to ldap server with user credentials from request
|
||||
err = conn.Bind(data.CN, data.Password)
|
||||
err = conn.Bind(data.Username, data.Password)
|
||||
if err != nil {
|
||||
// if bind fails return error - invalid credentials
|
||||
return apis.NewBadRequestError("Invalid credentials", err)
|
||||
|
|
|
@ -89,6 +89,12 @@ func upsertLDAPUser(app *pocketbase.PocketBase, ldapUser *LDAPUser) error {
|
|||
record = res
|
||||
} else { // if record does not exist, create it
|
||||
record = models.NewRecord(collection)
|
||||
// refresh token key only if new record is created
|
||||
// if record is updated, the token key should not be changed because it is used to authenticate the user
|
||||
// if the token key is changed, the user will be logged out
|
||||
if err := record.RefreshTokenKey(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
accountExpires, _ := ldapTimeToUnixTime(ldapUser.accountExpires)
|
||||
|
@ -117,8 +123,6 @@ func upsertLDAPUser(app *pocketbase.PocketBase, ldapUser *LDAPUser) error {
|
|||
record.Set("cn", ldapUser.cn)
|
||||
record.Set("memberOf", groups)
|
||||
|
||||
record.RefreshTokenKey()
|
||||
|
||||
if err := app.Dao().SaveRecord(record); err != nil {
|
||||
return fmt.Errorf("failed to upsert user with dn: %s - %w", ldapUser.dn, err)
|
||||
}
|
||||
|
@ -126,18 +130,30 @@ func upsertLDAPUser(app *pocketbase.PocketBase, ldapUser *LDAPUser) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// GetLdapGroupByDN This function returns a record from the ldap groups table by dn. It also expands the memberOf field.
|
||||
func GetLdapGroupByDN(app *pocketbase.PocketBase, dn string) (*models.Record, error) {
|
||||
return app.Dao().FindFirstRecordByFilter(
|
||||
record, err := app.Dao().FindFirstRecordByFilter(
|
||||
ldapGroupsTableName,
|
||||
"dn = {:dn}",
|
||||
dbx.Params{"dn": dn},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if errs := app.Dao().ExpandRecord(record, []string{"memberOf"}, nil); len(errs) > 0 {
|
||||
return nil, fmt.Errorf("ldap group - failed to expand: %v", errs)
|
||||
}
|
||||
return record, nil
|
||||
}
|
||||
|
||||
// GetLdapUserByCN This function returns a record from the ldap users table by cn. It also expands the memberOf field.
|
||||
func GetLdapUserByCN(app *pocketbase.PocketBase, cn string) (*models.Record, error) {
|
||||
return app.Dao().FindFirstRecordByFilter(
|
||||
ldapUsersTableName,
|
||||
"cn = {:cn}",
|
||||
dbx.Params{"cn": cn},
|
||||
)
|
||||
record, err := app.Dao().FindAuthRecordByUsername(ldapUsersTableName, cn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if errs := app.Dao().ExpandRecord(record, []string{"memberOf"}, nil); len(errs) > 0 {
|
||||
return nil, fmt.Errorf("ldap user - failed to expand: %v", errs)
|
||||
}
|
||||
return record, nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue