Designdokument for BROM

Selvbetjeningsportalen for RabbitMQ (BROM) er en tjeneste som tilbyr enkel administrasjon av notifikasjonsinfrastruktur.

<style type="text/css">/* :Author: David Goodger (goodger@python.org) :Id: $Id: html4css1.css 7056 2011-06-17 10:50:48Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to customize this style sheet. */ /* used to remove borders from tables and images */ .borderless, table.borderless td, table.borderless th { border: 0 } table.borderless td, table.borderless th { /* Override padding for "table.docutils td" with "! important". The right padding separates the table cells. */ padding: 0 0.5em 0 0 ! important } .first { /* Override more specific margin styles with "! important". */ margin-top: 0 ! important } .last, .with-subtitle { margin-bottom: 0 ! important } .hidden { display: none } a.toc-backref { text-decoration: none ; color: black } blockquote.epigraph { margin: 2em 5em ; } dl.docutils dd { margin-bottom: 0.5em } object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] { overflow: hidden; } /* Uncomment (and remove this text!) to get bold-faced definition list terms dl.docutils dt { font-weight: bold } */ div.abstract { margin: 2em 5em } div.abstract p.topic-title { font-weight: bold ; text-align: center } div.admonition, div.attention, div.caution, div.danger, div.error, div.hint, div.important, div.note, div.tip, div.warning { margin: 2em ; border: medium outset ; padding: 1em } div.admonition p.admonition-title, div.hint p.admonition-title, div.important p.admonition-title, div.note p.admonition-title, div.tip p.admonition-title { font-weight: bold ; font-family: sans-serif } div.attention p.admonition-title, div.caution p.admonition-title, div.danger p.admonition-title, div.error p.admonition-title, div.warning p.admonition-title { color: red ; font-weight: bold ; font-family: sans-serif } /* Uncomment (and remove this text!) to get reduced vertical space in compound paragraphs. div.compound .compound-first, div.compound .compound-middle { margin-bottom: 0.5em } div.compound .compound-last, div.compound .compound-middle { margin-top: 0.5em } */ div.dedication { margin: 2em 5em ; text-align: center ; font-style: italic } div.dedication p.topic-title { font-weight: bold ; font-style: normal } div.figure { margin-left: 2em ; margin-right: 2em } div.footer, div.header { clear: both; font-size: smaller } div.line-block { display: block ; margin-top: 1em ; margin-bottom: 1em } div.line-block div.line-block { margin-top: 0 ; margin-bottom: 0 ; margin-left: 1.5em } div.sidebar { margin: 0 0 0.5em 1em ; border: medium outset ; padding: 1em ; background-color: #ffffee ; width: 40% ; float: right ; clear: right } div.sidebar p.rubric { font-family: sans-serif ; font-size: medium } div.system-messages { margin: 5em } div.system-messages h1 { color: red } div.system-message { border: medium outset ; padding: 1em } div.system-message p.system-message-title { color: red ; font-weight: bold } div.topic { margin: 2em } h1.section-subtitle, h2.section-subtitle, h3.section-subtitle, h4.section-subtitle, h5.section-subtitle, h6.section-subtitle { margin-top: 0.4em } h1.title { text-align: center } h2.subtitle { text-align: center } hr.docutils { width: 75% } img.align-left, .figure.align-left, object.align-left { clear: left ; float: left ; margin-right: 1em } img.align-right, .figure.align-right, object.align-right { clear: right ; float: right ; margin-left: 1em } img.align-center, .figure.align-center, object.align-center { display: block; margin-left: auto; margin-right: auto; } .align-left { text-align: left } .align-center { clear: both ; text-align: center } .align-right { text-align: right } /* reset inner alignment in figures */ div.align-right { text-align: inherit } /* div.align-center * { */ /* text-align: left } */ ol.simple, ul.simple { margin-bottom: 1em } ol.arabic { list-style: decimal } ol.loweralpha { list-style: lower-alpha } ol.upperalpha { list-style: upper-alpha } ol.lowerroman { list-style: lower-roman } ol.upperroman { list-style: upper-roman } p.attribution { text-align: right ; margin-left: 50% } p.caption { font-style: italic } p.credits { font-style: italic ; font-size: smaller } p.label { white-space: nowrap } p.rubric { font-weight: bold ; font-size: larger ; color: maroon ; text-align: center } p.sidebar-title { font-family: sans-serif ; font-weight: bold ; font-size: larger } p.sidebar-subtitle { font-family: sans-serif ; font-weight: bold } p.topic-title { font-weight: bold } pre.address { margin-bottom: 0 ; margin-top: 0 ; font: inherit } pre.literal-block, pre.doctest-block, pre.math { margin-left: 2em ; margin-right: 2em } span.classifier { font-family: sans-serif ; font-style: oblique } span.classifier-delimiter { font-family: sans-serif ; font-weight: bold } span.interpreted { font-family: sans-serif } span.option { white-space: nowrap } span.pre { white-space: pre } span.problematic { color: red } span.section-subtitle { /* font-size relative to parent (h1..h6 element) */ font-size: 80% } table.citation { border-left: solid 1px gray; margin-left: 1px } table.docinfo { margin: 2em 4em } table.docutils { margin-top: 0.5em ; margin-bottom: 0.5em } table.footnote { border-left: solid 1px black; margin-left: 1px } table.docutils td, table.docutils th, table.docinfo td, table.docinfo th { padding-left: 0.5em ; padding-right: 0.5em ; vertical-align: top } table.docutils th.field-name, table.docinfo th.docinfo-name { font-weight: bold ; text-align: left ; white-space: nowrap ; padding-left: 0 } h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, h4 tt.docutils, h5 tt.docutils, h6 tt.docutils { font-size: 100% } ul.auto-toc { list-style-type: none } </style> <div class="document" id="mal-for-designdokumenter"> <div class="section" id="innledning"> <h2>1 Innledning</h2> <div class="user-content-block"> <p>I en integrasjonsarkitektur som baserer seg på APIer for datauttrekk er det essensielt at konsumerende tjenester kan få beskjed om at informasjonen i et API har blitt endret, slik at informasjonen kan behandles uten at det komplette settet med informasjon som er tilgjengelig via APIet konsumeres. Beskjedene om endring i datagrunnlag kalles for notifikasjoner.</p> <p>Notifikasjoner trenger livsløpsforvaltning på lik linje med API-er. For API-er er dette tilbudt via en API Manager, som lar API-eiere forvalte tilgangene samtidig som den håndhever hvem som får gjøre uttrekk fra API-et.</p> <p>For å oppnå samme grad av livsløpsforvaltning for notifikasjoner trengs det et grensesnitt som tilbyr følgende funksjonalitet:</p> <p style="margin-left: 40px;">I denne sammenheng brukes begrepene konsument og produsent om applikasjoner. En konsument er en applikasjon som tar i mot notifikasjoner fra andre applikasjoner, mens en produsent er en applikasjon som publiserer notifikasjoner som andre applikasjoner kan ta i mot.</p> <ul> <li>Enkel og brukervennlig gjør-det-selv administrasjon, slik at <ul> <li>produsenter kan tilgjengeliggjøre notifikasjoner fra sitt system.</li> <li>konsumenter kan søke om abonnement på notifikasjoner som er interessante.</li> <li>produsenter kan godkjenne konsumenters ønske om abonnement på forskjellige notifikasjonstyper.</li> </ul> </li> <li>Enkel og brukervennlig administrasjon av hemmeligheter som benyttes til autentisering.</li> <li>Synkronisering av informasjon om abonnementer og hemmeligheter til RabbitMQ, med hensyn til utførelse av autentisering og autorisasjon av konsumenter og produsenter.</li> <li>Katalog over hvilke systemer som produserer notifikasjoner er tilgjengelig.</li> <li>Katalog over hvilke systemer som konsumerer notifikasjoner er tilgjengelig.</li> </ul> </div> <h3>1.1 Brukerroller</h3> <p>Selvbetjeningsgrensesnittet er i hovedsak myntet på produsenter og konsumenter, uten noen spesifikk avgrensning til om det er beslutningstakere eller teknisk personell som utfører operasjoner.</p> <h3>1.2 Kontakt</h3> <ul> <li class="elm-has-own-text">Systemeier: <a href="/om/organisasjon/iti/int/ansatte/jokim/index.html">Joakim Hovlandsvåg (Seksjonssjef for USITINT)</a></li> <li class="elm-has-own-text">Drift: <a class="reference external vrtx-link-check vrtx-link-check" href="https://www.usit.uio.no/om/organisasjon/bnt/usitint/" target="vrtx-preview-window">Seksjon for integrasjon og elektroniske identiteter (USITINT)</a></li> <li class="elm-has-own-text">Utvikling: <a class="reference external vrtx-link-check vrtx-link-check" href="https://www.usit.uio.no/om/organisasjon/bnt/usitint/" target="vrtx-preview-window">Seksjon for integrasjon og elektroniske identiteter (USITINT)</a></li> </ul> </div> <div class="section" id="redegjorelse"> <h2>2 Redegjørelse</h2> <h3>2.1 Bakgrunn</h3> <p>Forprosjektet som utredet innføring av UH:IntArk (2018-2019) identifiserte behovet for livsløpsforvaltning av notifikasjoner på lik linje med livsløpsforvaltning av APIer. Tjenesten anses dermed som en komponent i IntArk-plattformen.</p> <p>Forprosjektet anbefalte implementasjon av en løsning som ville</p> <ul> <li>tilgjengeliggjøre informasjon om notifikasjoner for produsenter</li> <li>forenkle administrasjon av notifikasjonsinfrastrukturen</li> <li>ivareta sikkerhet</li> <li>sørge for eierskap og ansvarliggjøring av produsenter</li> </ul> <h3>2.2 RabbitMQ tilgangskontroll</h3> <p>Tilgangskontroll for RabbitMQ er flyttet til selvbetjeningsportalen. Konsekvensen er at nedetid for selvbetjeningsportalen vil føre til at applikasjoner ikke kan konsumere eller publisere notifikasjoner.</p> <h3>2.3 Eksterne produsenter</h3> <p><a href="https://jira.usit.uio.no/browse/BROM-44">Det finnes foreløpig ikke noe funksjonalitet for å håndtere eksterne produsenter via selvbetjeningsportalen</a>. For å få notifikasjoner fra eksterne produsenter inn i sin egen RabbitMQ-instans må man derfor manuelt opprette en spade som spar notifikasjoner fra produsenten sin RabbitMQ-instans. Ideelt sett ville det vært mulig å abonnere på notifkasjonene til eksterne produsenter fra selvbetjeningsportalen, men dette er vanskelig å implementere så lenge eksterne instanser ikke følger et standardisert oppsett.</p> </div> <div class="section" id="detaljebeskrivelse"> <h2>3 Detaljebeskrivelse</h2> </div> <div class="section" id="hoynivadesign-overordnet-design"> <h3>3.1 Høynivådesign (Overordnet design)</h3> <p>Den overordnede flyten avhenger av flere ulike komponenter. Brukerene interagerer med tjenesten gjennom vevgrensesnittet.</p> <figure class="image"><img alt="Bildet kan inneholde: produkt, skrift, rektangel, parallell, skråningen." height="401" src="/om/organisasjon/iti/int/faglig/designdokumenter/brom-filer/brom.svg" width="591" loading="lazy"/> <figcaption>Figur1: Overordnet designskisse</figcaption> </figure> <ol> <li>Pålogging (autentisering) skjer gjennom Feide. Ved pålogging blir brukeren sine gruppemedlemskap hentet fra Feide, og gruppemedlemskapene synkroniseres til selvbetjeningsportalen. Disse gruppene kan senere brukes til tilgangsstyring. Første gang en bruker logger på, blir det opprettet en brukerkonto i selvbetjeningsportalen.</li> <li>Gjennom vevgrensesnittet kan brukeren opprette applikasjoner, be om å abbonnere på andre applikasjoner sine notifikasjoner, eller håndtere inkommende forespørsler om å få abonnere på notifikasjoner. Hver av disse handlingene fører til at objekter opprettes eller endres i databasen.</li> <li>Det er en separat prosess (demon) som kontinuerlig synkroniserer ønsket tilstand til RabbitMQ. Denne utleder ønsket tilstand i RabbitMQ fra objektene som finnes i selvbetjeningsportalen.</li> <li>Når et abonnement har blitt godkjent og synkronisert, vil en konsument kunne begynne å konsumere notifikasjoner.</li> <li>Det kreves autorisasjon for at en bruker skal få lov til å gjennomføre handlinger i RabbitMQ, for eksempel om en konsument vil konsumere en melding fra en kø. RabbitMQ kan konfigureres til å flytte sjekkene for autentisering og autorisasjon til et eksternt API. I vårt tilfelle er det selvbetjeningsportalen som står for å gjøre disse sjekkene. Hver gang noen ber om å gjøre en handling som krever autorisasjon i RabbitMQ, gjør RabbitMQ en spørring mot selvbetjeningsportalen sitt API som svarer på om handlingen skal tillates. Forespørsler tillates eller avslås på grunnlag av data som finnes i selvbetjeningsportalen.</li> </ol> </div> <div class="section" id="lavnivadesign-design-av-enkeltkomponenter"> <h3>3.2 Lavnivådesign (Design av enkeltkomponenter)</h3> <p>Teknisk kan tjenesten deles opp i flere logiske deler basert på hvilken oppgave de utfører. De tre første av disse delene er alle inkludert i applikasjonen sitt <a href="https://bitbucket.usit.uio.no/projects/BROM/repos/brom/browse">repo</a>.</p> <h4>3.2.1 Vevgrensesnitt</h4> <p>Tjenesten er skrevet i python og benytter web-rammeverket <a href="https://www.djangoproject.com/">Django</a>. Den består av statiske nettsider, men noen av disse statiske nettsidene har innbakte javascript-komponenter i seg. Komponentene interagerer med tjenestens endepunkt for å hente, poste og slette data, slik at endringer kan fremvises dynamisk.</p> <h4>3.2.2 Dæmon</h4> <p>Tjenesten består i tillegg av en dæmon som kjører og kontinuerlig leter etter nye endringer som trenger å synkroniseres til RabbitMQ. Når en usynkronisert endring har blitt funnet, gjøres det et forsøk på å synkronisere endringen på bakgrunn av de data som finnes i tjenesten.</p> <h4>3.2.3 RabbitMQ tilgangskontroll</h4> <p>Som nevnt under punkt 3.1, har RabbitMQ blitt satt opp til å bruke selvbetjeningsportalen for tilgangskontroll. Dette skjer ved at det selvbetjeningsportalen tilgjengeliggjør ulike endepunkter som RabbitMQ kan gjøre spørringer mot. Hvilket endepunkt som blir kalt avhenger av hvilken ressurs brukeren ber om tilgang til.</p> <figure class="image"><img alt="Skisse over tilgagskontroll" height="128" src="/om/organisasjon/iti/int/faglig/designdokumenter/brom-filer/brom-permission-control.svg" width="600" loading="lazy"/> <figcaption>Figur2: Skisse over tilgagskontroll</figcaption> </figure> <h4>3.2.4 Mikrotjeneste for sletting av spader</h4> <p>En <a href="https://github.com/rabbitmq/rabbitmq-server/issues/2807">bug</a> i RabbitMQ gjør at spader ikke kan slettes pålitelig via RabbitMQ sitt management-API. Kort fortalt består problemet i at forespørsler om å slette spader vil ende opp på en tilfeldig node. For at sletting skal fungere som forventet, må forespørselen ende opp på samme RabbitMQ-node som spaden kjører på. <a href="https://bitbucket.usit.uio.no/projects/BROM/repos/rabbitmq-shovel-terminator/browse">Mikrotjenesten</a> kjører i samme Openshift-prosjekt som RabbitMQ og tar hånd om å sjekke hvilken node en spade kjører på før den sender kallet videre til riktig node.</p> <figure class="image"><img alt="Infrastrukturskisse" height="359" src="/om/organisasjon/iti/int/faglig/designdokumenter/brom-filer/rabbitmq-shovel-terminator.svg" width="600" loading="lazy"/> <figcaption>Figur3: Skisse over infrastruktur</figcaption> </figure> <h4>3.2.5 Klient for kommunikasjon med RabbitMQ</h4> <p>Funksjonaliteten for å kommunisere med RabbitMQ sitt management-API er implementert i et eget gjenbrukbart <a href="https://bitbucket.usit.uio.no/projects/BROM/repos/pyrabbit2/browse">bibliotek</a>.</p> </div> <div class="section" id="avhengigheter"> <h2>4 Avhengigheter</h2> <p>Konkrete systemer/tjenester og en kort beskrivelse av hva avhengigheten går ut på.</p> <h3>4.1 Feide</h3> <p>Tjenesten er avhengig av Feide for autentisering av brukere.</p> <h3>4.2 RabbitMQ</h3> <p>Tjenesten har en gjensidig avhengighet med RabbitMQ.</p> <h3>4.3 NREC</h3> <p>Produksjonsversjonene av applikasjonen kjører i <a href="https://www.uio.no/tjenester/it/hosting/iaas/">NREC</a>.</p> </div> <div class="section" id="lenker-og-referanser"> <h2>5 Lenker og referanser</h2> <ul class="simple"> <li><a href="https://bitbucket.usit.uio.no/projects/BROM">Kode i bitbucket</a></li> <li><a href="https://brom-uio.intark.uh-it.no">brom-uio</a></li> <li><a href="https://brom-uib.intark.uh-it.no">brom-uib</a></li> <li><a href="https://brom-uio-staging.uio.no/">brom-uio-staging</a></li> </ul> </div> </div> </div> </div> <div class="vrtx-date-info"> <span class="published-date-label">Publisert</span> <span class="published-date">15. mars 2021 11:56 </span> <span class="separator-date"> - </span> <span class="last-modified-date">Sist endret</span> <span class="last-modified-date">13. jan. 2023 12:56</span> </div> <div class="vrtx-social-components"> <a class="vrtx-email-friend" title='Del på e-post' href="mailto:?subject=Designdokument%20for%20BROM&body=https%3A%2F%2Fwww.usit.uio.no%2Fom%2Forganisasjon%2Fiti%2Fint%2Ffaglig%2Fdesigndokumenter%2Fdesigndokument-brom.html"> Del på e-post</a> <div class="vrtx-share-at-component"> <ul> <li class="vrtx-share-at-Facebook"> <a href="https://www.facebook.com/sharer.php?u=https%3A%2F%2Fwww.usit.uio.no%2Fom%2Forganisasjon%2Fiti%2Fint%2Ffaglig%2Fdesigndokumenter%2Fdesigndokument-brom.html" target="_blank" class="facebook"> Del på Facebook</a> </li> <li class="vrtx-share-at-X"> <a href="https://x.com/intent/tweet?text=Designdokument+for+BROM&amp;url=https%3A%2F%2Fwww.usit.uio.no%2Fom%2Forganisasjon%2Fiti%2Fint%2Ffaglig%2Fdesigndokumenter%2Fdesigndokument-brom.html" target="_blank" class="x"> Del på X</a> </li> </ul> </div> </div> </div> </div> <!--stopindex--> </main> </div> <!-- Page footer start --> <footer id="footer-wrapper" class="grid-container faculty-institute-footer"> <div id="footers" class="row"> <div class="footer-content-wrapper"> <div class="footer-title"> <a href="https://www.usit.uio.no/">IT-avdelingen</a> </div> <div class="footer-content"> <div> <h2>Kontakt</h2> <p><a href="/om/kontaktinformasjon/">Kontakt oss</a><br> <a href="/om/finn-fram/">Finn frem</a></p> </div> <div> <h2>Om nettstedet</h2> <p><a href="https://www.uio.no/om/regelverk/personvern/personvernerklering-nett.html">Bruk av informasjonskapsler</a><br> <a href=" https://uustatus.no/nb/erklaringer/publisert/9336562c-fbb2-48db-b3f2-54df3b231a44">Tilgjengelighetserklæring</a></p> </div> </div> <div class="footer-meta-admin"> <h2 class="menu-label">Ansvarlig for denne siden</h2> <p> <a href="mailto:webredaksjon@usit.uio.no">Nettredaksjonen, IT-avdelingen</a> </p> <div class="vrtx-login-manage-component"> <a href="https://www.usit.uio.no/om/organisasjon/iti/int/faglig/designdokumenter/designdokument-brom.html?authTarget" class="vrtx-login-manage-link" rel="nofollow"> Logg inn </a> </div> </div> </div> </div> </footer> <nav class="grid-container grid-container-top" id="footer-wrapper-back-to-uio"> <div class="row"> <a class="back-to-uio-logo" href="https://www.uio.no/" title="Gå til uio.no"></a> </div> </nav> <script type="module" src='/vrtx/dist/resources/uio2/js/uio2.js'></script> </body> </html>