Alkalmazások beállítása
Egy alkalmazás egy apps.yaml-bejegyzéssel kerül az ISG-belépés mögé minden brókeren, vagy — dinamikus
alkalmazás-domain mellett — egy adminisztrátor veszi fel a webUI-n. Ez a lap mindkét utat leírja, a három módot,
ahogy egy alkalmazás megtudja, ki a felhasználó, és hogy mit kell az ügyfél oldalán biztosítani. A teljes
kulcslista a konfigurációs referenciában áll; a forrásfa apps.example.yaml fájlja minden
kulcsot kommenttel hordoz.
Hiányzó apps.yaml mellett a Web Access ki van kapcsolva, és a démon úgy indul, mint eddig. Egy meglévő, de be nem
töltő apps.yaml mellett a démon nem indul el, és a hiba megnevezi a fájlt és a mezőt; az isg system check
ugyanazt a betöltőt futtatja (az apps.yaml sor). A Web Access-hez a webUI jelszavas belépése kell egy
identitás-forrással szemben: anélkül a démon ezzel a fájllal nem indul.
A szállított Ansible-lel
A kapcsoló a környezet változói közt az isg_cfg_apps: alkalmazásonként egy bejegyzés, az apps.example.yaml
mezőivel. Üresen a Web Access ki van kapcsolva, és nem íródik apps.yaml. Minden bejegyzéshez egy
APP-2026-000001 alakú id kell, egyedi, és soha nem adható másik alkalmazásnak: a jóváhagyások, a munkamenetek, a
zárak, a ticketek és az auditnapló (app_id) mind ezzel hivatkoznak az alkalmazásra, a name pedig a technikai név
marad (a JWT audience és az OpenBao-út). Beállítva egy futás ezt teszi:
- A
playbooks/config-src.ymlmegírja azapps.yaml-t, a listener tanúsítványát (tls/apps.crt) a kulcsával (tls/apps.key), és az assertion kulcspárt (apps/assertion.key,apps/assertion.pub,apps/assertion.jwks.json). Azisg_config_src_pki_enabledmellett a role a tanúsítványt a környezet gyökere alatt adja ki, minden alkalmazás-hosztra; nélküle az ügyfél saját párjának kell előbb ott lennie, különben a futás megáll, mielőtt bármit írna. - A
playbooks/site.ymlkiviszi a fájlokat a brókerekre, amelyek azisg_apps_port-on figyelnek (alapból 8444; nem 8443, amit egy tesztelő gépe általában már az identity providerre továbbít). - A monitoring-gép. Ha egy
identity: jwtalkalmazás upstreamje ez a gép, a Grafana[auth.jwt]-t kapjwk_set_file-lal: a config-forrás JWKS-fájljával, így a Grafana sem a brókerektől, sem a névfeloldástól nem függ. Az upstream portok azisg_monitoring_firewall_app_sources-on át nyílnak a brókerek felé (a levélgyűjtőé azisg_directory_firewall_mail_ui_app_sources-on át); egy üresisg_monitoring_firewall_admin_sourceslezárja a közvetlen utat, így a konzol csak az ISG-n át érhető el.
Egy alkalmazás változása konfiguráció-változás: a config-src.yml megírja az új apps.yaml-t, és a gördülő
frissítés viszi ki brókerenként. Önmagában a bináris cseréje nem.
A listener és a tanúsítványa
| Kulcs | Mi az |
|---|---|
listen |
A TLS-listener címe, minden alkalmazáshoz |
tls_cert_file, tls_key_file |
A listener lánca és kulcsa (a kulcs 0600 vagy 0400); a levélnek minden host-ot le kell fednie |
webui_url |
A webUI címe: ide küldi a proxy a böngészőt belépni, és ide tér vissza kilépéskor |
idle_timeout_seconds, max_duration_seconds |
Az alkalmazás-munkamenet tétlenségi (1800 s) és abszolút határa (28800 s), a webUI-étól függetlenül |
reserved_usernames |
Nevek, amik sosem érnek el egy alkalmazást (alapból admin, root, administrator) |
credential_kv_prefix |
Hol élnek a közös fiókok OpenBao-ban (alapból isg/apps) |
dynamic_apps_domain |
A webUI-n felvett alkalmazások domainje; üres = nincs |
Amit az ISG nem végez el helyetted: a DNS. Minden alkalmazás-hosztnévnek a brókerek közös címére kell feloldódnia,
és a webUI-jal azonos site-on kell lennie — a webUI munkamenet-sütije SameSite=Strict. A kliens az alkalmazások
tanúsítványában ugyanúgy bízik, mint a webUI-éban.
Egy alkalmazás
- id: APP-2026-000002
name: prometheus
display_name: Prometheus
host: prometheus.apps.example.internal
upstream: http://monitor1.example.internal:9090
identity: none
allow_groups: [sysadmins]
- A
name[a-z0-9-]{1,32}alakú, és nem változik: ez a JWT audience alapértéke és az OpenBao-út. Adisplay_nameaz, amit az emberek olvasnak. - A
hostDNS-név (nem IP), az alkalmazások között egyedi. - Az
upstreamhttp(s)://host[:port]útvonal nélkül; egyhttpsupstreamnél azupstream_ca_filenevezi meg a CA-ját. - Az
allow_groupskötelező és nem üres: nincs olyan alkalmazás, ami minden belépett felhasználó előtt nyitva áll. - A
logout_paths(például/logout) azok az utak, ahová az alkalmazás saját kilépés-gombja visz; egy oda menő kérés kilépteti a felhasználót az alkalmazás-munkamenetből. - A
level(0–5) az alkalmazás zárolási szintje: ajira.yamlticket_min_levelküszöbén egy Web Access-munkamenet ticketet nyit, mint egy SSH-munkamenet. - A jóváhagyás, az önkiszolgáló hozzáférés, a kérés-rögzítés és a kérés-szabályok a Web Access-policy lapon állnak.
Mit tud meg az alkalmazás a felhasználóról
identity: none
Az ISG kapuz és auditál; az alkalmazás semmit nem tud meg. Saját felhasználó-fogalom nélküli konzolhoz (Prometheus, egy levélgyűjtő), vagy olyanhoz, aminek egyetlen közös nézet is megfelel.
identity: jwt
Minden kérés egy friss assertiont visz az assertion_header-ben (alapból X-ISG-Assertion), ES256-tal aláírva
(assertion_key_file, egy ECDSA P-256 kulcs): sub, email, name, groups, aud (az audience, alapból a
name), iss (az assertion_issuer, alapból isg), és a role a role_map-ből (az első egyező csoport nyer),
különben a default_role. assertion_ttl_seconds ideig érvényes (alapból 60, 10–300). A nyilvános kulcs minden
alkalmazás-hoszton a /.well-known/isg/jwks.json címen van. Az alkalmazás a sub-ot a saját, azonos nevű helyi
fiókjára képezi — ezért vannak a tiltott nevek: a Grafanán mérve a sub: admin a beépített szuperadmin lett.
identity: credential
Az ISG egy közös fiók titkát teszi a kérésbe; a felhasználó sosem látja, és a saját neve az ISG auditjában és
transcriptjében marad (account). A credentials lista: az első olyan elem kerül használatba, amelynek groups-a
metszi a felhasználó csoportjait, és ha egyik sem, a válasz 403 — csendes alapértelmezett fiók nincs. A titkot az ISG
OpenBao-ból olvassa a <kv_mount>/data/<prefix>/<app>/<name> úton, ahol a <prefix> a credential_kv_prefix, ezért
egy ilyen alkalmazás mellett a vault.yaml kötelező. Ha nem olvasható, a kérés nem megy fel (503).
kind |
Mi megy fel | OpenBao-mezők |
|---|---|---|
basic |
Authorization: Basic |
username, password |
header |
a bejegyzésen megnevezett header (pl. X-Api-Key) |
value |
form |
egy olyan fiók upstream munkamenet-sütijei, amivel az ISG maga lépett be | username, password, opcionális totp_secret |
A böngésző saját Authorization fejléce és a megnevezett fejlécek minden kérésből törlődnek, és az upstream
WWW-Authenticate válaszfejléce is, így a böngésző sosem nyit saját jelszó-ablakot.
Űrlappal belépő konzol (kind: form)
A fiók form receptje a konzol saját belépése, lépésről lépésre: steps (egy GET csak tokent nyer ki; legalább
egy POST; encoding: form vagy json; a mezők értéke literál vagy {{username}}, {{password}}, {{totp}},
{{token.<name>}}), success (a megadott status, cookie, redirect_prefix mindegyikének teljesülnie kell az
utolsó lépés válaszán) és logged_out (mikor jelenti egy válasz, hogy az upstream munkamenet véget ért: status,
vagy egy 3xx, amelynek a Location-je redirect_prefix-szel kezdődik).
credentials:
- name: admin
groups: [sysadmins]
kind: form
form:
steps:
- method: POST
path: /login
encoding: json
fields: {user: '{{username}}', password: '{{password}}'}
success: {status: [200], cookie: grafana_session}
logged_out:
status: [401]
redirect_prefix: /login
unless_body_contains: [session.token.rotate]
- A belépés alkalmazás-munkamenetenként és fiókonként egyszer történik, az első kérésnél; a párhuzamos kérések
ugyanarra a belépésre várnak. Az
APP_UPSTREAM_LOGINauditálva van (relogin: true-val, ha megújítás). - Ha az upstream munkamenet véget ér, az ISG újra belép. Egy
GET-et vagyHEAD-et egyszer, láthatatlanul megismétel; minden más metódus egy 409-es oldalt kap, ami újraküldést kér, mert egy módosító kérést sosem ismétel meg a felhasználó háta mögött. - Egy sikertelen belépés 502-es oldalt ad; az
APP_UPSTREAM_LOGIN_FAILEDmegnevezi, miért (status,success_cookie,success_redirect,extract,timeout,transport,secret), értéket sosem. - Az
unless_body_containsszűkíti alogged_out-ot: egy válasz, aminek az első 8 KiB-ja a szövegek egyikét tartalmazza, az alkalmazás üzenete a saját front-endjének, nem kiléptetés, és változatlanul megy a böngészőnek. A Grafana token-forgatása az az eset, amiért létezik (lásd egy webes konzol előkészítése). - A
browser_cookiesazokat a sütiket sorolja fel, amik mindkét irányban átmennek, és amiket a bróker nem tart meg (például egy CSRF-süti, amit az oldal szkriptje olvas); egyisg_nevet elutasít. - Felfelé menet a böngésző
OriginésRefererfejléce az upstream saját címére íródik, ha az az alkalmazás nyilvános címe — egy konzol, ami egy sütivel hitelesített kérés eredetét ellenőrzi, így elfogadja. Egy idegen origin változatlanul megy fel, így a konzol saját CSRF-védelme megmarad. - Nem támogatott: a captcha, és egy token, amit a konzol szkriptje maga ad tovább (például egy BMC, ami a munkamenet-tokenjét az oldal tárában tartja).
A webUI-n felvett alkalmazások
Ha az apps.yaml-ben a dynamic_apps_domain be van állítva, egy adminisztrátor a webUI Appok kezelése oldalán
(/apps/manage) vesz fel, módosít és töröl alkalmazásokat a fájlbeliek mellett; minden bróker kb. 5 s alatt,
újraindítás nélkül kiszolgálja a változást. Minden ilyen alkalmazás hosztja egy címke e domain alatt, ezért két dolog
egyszeri beállítás az ügyfél oldalán: a listener tanúsítványának wildcard SAN kell a domainre (csillag-pont-domain;
az apps.yaml betöltésekor ellenőrizzük, a hiánya megtagadja az indulást), és egy wildcard DNS-rekordnak kell a
domaint a brókerek közös címére mutatnia. A fájlbeli alkalmazások úgy maradnak, ahogy vannak, és a webUI-n nem
szerkeszthetők. Ansible-lel a domain az isg_cfg_apps_dynamic_domain; ha a role adja ki az alkalmazás-tanúsítványt,
a wildcard SAN-t maga hozzáadja. Az ISG minden ilyen alkalmazás azonosítóját a rekord-tár sorszámából adja; egy
törlés és azonos néven újrafelvétel új alkalmazás, így a régi jóváhagyásai közül egy sem száll át. Egy dinamikus
alkalmazás nem kapcsolhatja be a record_body-t.