From 7d73560599b50f8f5248716c62f50c2238122934 Mon Sep 17 00:00:00 2001 From: Tore Brede <Tore.Brede@uib.no> Date: Mon, 23 Aug 2021 10:26:13 +0200 Subject: [PATCH] GREG-22: Adding first version of documentation --- doc/DESIGN.md | 94 ++++++++++++++++++++++++++++++++++++ doc/overview_components.png | Bin 0 -> 19212 bytes 2 files changed, 94 insertions(+) create mode 100644 doc/DESIGN.md create mode 100644 doc/overview_components.png diff --git a/doc/DESIGN.md b/doc/DESIGN.md new file mode 100644 index 00000000..4d76211d --- /dev/null +++ b/doc/DESIGN.md @@ -0,0 +1,94 @@ +# Designdokument for gjesteregistreringsløsning + + +## Innledning +Gjesteregistreringsløsningen (GREG, Guest REGistation) tilbyr et grensesnitt der institusjoner kan legge inn data +om personer som trenger gjestekontoer for å få tilgang til IT-tjenester. Tjenesten kan integrere med institusjonens IAM (Identity and access management) +løsning for overføring av data til denne. + +Hver institusjon som ønsker å bruke GREG vil ha sin egen instans som bare inneholder +data om brukere ved den institusjonen. + +GREG kan på lang sikt komme til å bli erstattet av gjestehåndtering i et personalsystem. + +### Brukerroller +Det er to brukerkategorier i tjenesten: +- Sponsorer: Dette er brukere ved institusjonene som kan invitere gjestebrukere +- Gjester: Dette er personer lagt inn av sponsorer og som ønsker tilgang til IT-systemene ved institusjonen + +### Kontakt +- Systemeier: *TODO* + +## Redegjørelse +Dagens løsning i DFØ-SAP for å registrere gjestebrukere dekker ikke behovene til UiO og UiB, og det ble avgjort å utvikle +en alternativ løsning for å få et system mer i tråd med behovene på plass innen kort tid. + +Systemet består av to deler, en kjerne og en selvbetjeningsløsning, og kommunikasjon mellom disse skjer gjennom et +REST API kjernen gjør tilgjengelig. + +Ved å splitte funksjonaliteten på denne måten er teknologivalg gjort i selvbetjeningsløsningen, som er frontenden +sluttbrukerne ser, uavhengig av kjernen. Så utviklerne kan på hver sine side, frontend og backend, velge teknologier de er komfortable med. + + +### Designvalg + +#### Kjerne +Kjernen er utviklet med Django, et populært webrammeverk i Python som har mange tilleggsmoduler +som gjør utviklingen enklere. USIT har kompetanse på Django, og det er allerede brukt i Kada og Mreg. + +#### Selvbetjeningsløsning +*TODO* + +## Detaljbeskrivelse + +### Teknisk formål +Kjernen har som hovedoppgave å lagre data om gjestene, sende notifikasjoner om relevante endringer +via en meldingskø og tilby et REST API for å lagre og hente ut data. + +Endringer som det publiseres meldinger for inkluderer opprettelse av nye gjester i kjernen, endring gjort på +eksisterende gjester og sletting av gjester. + +IAM-systemet ved en institusjon kan lytte på meldingskøen kjernen publiserer til for å bli gjort oppmerksom +på endringer for gjester. Informasjonen i meldingene kan brukes til å gjøre oppslag i API'et. + +Kjernen vil også periodisk slette persondata for gjester som ikke lenger er aktive. + +Adgangskontroll til API'et skjer gjennom Gravitee. + +Selvbetjeningsløsningen lar sponsorer opprette gjester og lar gjestene legge inn identitetsinformasjon. Det er +selvtjeningsløsningen som har ansvaret for flyten gjennom registreringsforløpet, dvs. den sender for eksempel ut e-poster +til gjestene om at de må legge inn informasjon og til sponsorene om at de må godkjenne gjester som har lagt inn informasjon. + +Selvbetjeningsløsningen bruker kjernen hovedsaklig for å lagre informasjon. + +### Høynivådesign + + +### Lavnivådesign + +#### Kjerne +For å tilby et REST API brukes "Django REST framework". +En [OpenAPI](https://swagger.io/specification/) spesifikasjon av API'et er tilgjengelig +(generert ved hjelp av [drf-spectacular](https://github.com/tfranzel/drf-spectacular)) + +Sending av meldinger til RabbitMQ skjer ved hjelp av [pika-context-manager](https://git.app.uib.no/it-bott-integrasjoner/pika-context-manager) biblioteket. + +Tilgangskontroll til API'et skjer via Gravitee. Brukerne av API'et er selvbetjeningsløsningen og +institusjonens IAM-system. + +### Selvbetjeningsløsning +*TODO* + +## Avhengigheter +- RabbitMQ: Brukes for å sende meldinger til andre systemer +- Harbor: Lagring av container images +- Openshift: Applikasjonsplattform for å kjøre containere +- Gravitee: Tilgang til API styres gjennom Gravitee +- Institusjonens IAM system. + +## Relaterte systemer +- Cerebrum: Brukeradministrasjonssystem ved UiO. Henter data fra GREG og oppretter brukerkontoer. Sender data tilbake til Greg om hvilke gjester som har fått brukerkontoer. +- RI: Brukeradministrasjonssystem ved UiB. Opererer etter samme mønster integrasjonen mellom Cerebrum og GREG. + +## Lenker og referanser +Koden til GREG finnes på UiB sin Gitlab-instans [her](https://git.app.uib.no/it-bott-integrasjoner/greg). \ No newline at end of file diff --git a/doc/overview_components.png b/doc/overview_components.png new file mode 100644 index 0000000000000000000000000000000000000000..2f00e01d00035582482501663cc7c2bb3996c0b2 GIT binary patch literal 19212 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 literal 0 HcmV?d00001 -- GitLab