LPS:IdM/midPoint/Office365
Info
Microsoft Office365 - cloudová aplikace. Identity jsou spravované přes Graph API.
- Resource: Office365
- Endpoint: https://office365.zcu.cz
- Git:
- Tenant:
- 10469a73-68e0-41ec-8155-3f785e4870be / zcutest.onmicrosoft.com (vývoj)
- 9bd5c768-90b8-4e4f-8416-147729d91c53 / zcu365.onmicrosoft.com (produkce)
Admin přístup pro IdM
- https://office365.zcu.cz
- Admin Center -> Azure Active Directory -> Azure Active Directory -> App registrations
- identita "OpenICF MSGraph Connector" -> Client credentials
==> hlavní ID použít Application (client) ID
==> heslo použít secret z Client credentials
==> (lze si zvolit dobu platnosti, ale max. je 2 roky)
Konektor
Máme vlastní fork s drobnými odlišnostmi:
- jiné závislosti pro runtime a build (aby byly podobné verze s midPointem na ZČU)
- do upstramu jsme přispěli vlastními změnami (optimalizace, opravy, podpora licencí)
Model
| kind | objectClass | intent | focus | význam |
|---|---|---|---|---|
| account | AccountObjectClass | - | UserType | osoba |
| entitlement | GroupObjectClass | group | OrgType | skupiny (nepoužíváme) |
| generic | CustomlicenseObjectClass | license | OrgType | licence |
Osoby
Zaměstnanci, studenti, rozšířená hostovská konta (je vyžadováno CRO ID).
Primární klíče:
- __NAME__ - LOGIN@DOMAIN
- onPremisesImmutableId - CRO ID (nikdy se nesmí měnit)
- userPrincipalName - LOGIN
Atributy:
- mail: LOGIN@DOMENA, jen přo zakládání, ale nelze spravovat přes Graph API
- proxyAddresses: jen ke čtení. Obsahuje e-mailové adresy. Tímto atribuem lze detekovat potíž po přejmenování, kdy je potřeba ruční zásah.
- password:
- povinné, i když se nepoužívá
- nesmí obsahovat příliš speciální znaky
- generujeme náhodné, aby tam něco bylo
Merge: nelze
Povolení/blokace: 1:1 podle identity v midPointu
Přesměrování e-mailů: nelze spravovat přes Graph API. Nastavování přesměrování ve skriptech mimo režii IdM.
Přejmenování: potřeba ruční zásah kolem správy emailů. Původní email je u přejmenovávané identity ponechán. Existují ruční postupy přes skripty, jak to čistit.
Fyzické mazání: Pro konta ve stavu BD (blokované 2 roky). Po smazání je identita v koši po dobu 1 měsíce. Po tuto dobu ji nelze znovuzaložit automaticky přes Graph API. Lze ji obnovit přes administrátorské rozhraní Office 365, anebo smazat vývojovými administrátorskými nástroji (koš nelze vysypat přes midPoint - umí to Graph API, ale identity mají divoké identifikátory).
Skupiny
Z IdM neudržujeme, teoreticky je možné.
Licence
Read-only identity. V midPointu použito pro výpočty atributů pro přidělováné licencí (technicky: jde o "ruční" query, nelze použít přímo asociace na resourcu).
Licence se skládá z jednotlivých aplikací.
Pro každou licenci lze nastavit globální vyjímku pro nějakou aplikaci. Ale nelze nastavovat různé vyjímky pro každého uživatele (technicky: přes Graph API to lze, ale vedlo by to na strukturovaný atribut u uživatele).
Výpočet licencí
Princip
Šílenost. Vychází se z dokumentu: https://software.zcu.cz/files/MS_EES.html
V zásadě dva typy licencí: A1 a A3 a každá z nich má studentskou a zaměstnaneckou verzi.
- Typ studentské se volí podle fakulty (==> GROUP: o365proplus-students)
- Typ zaměstnanecké podle self-managementu (SELF: O365 PRACOVISTE), ale jen pro vybraná pracoviště (==> GROUP: o365proplus-PRACOVISTE). Mimofakultní mají ještě rozdělený self-management, ale slévají se do jednoho GROUP: o365proplus-rek. Pak je ještě MNG: O365 SPECIAL pro zaměstnaneckou A3 licenci bez hlídání, zda jde o zaměstnance na správném pracovišti (např. i hostovská konta).
- Přičítá se ještě PowerBI Pro na základě ručně udržované skupiny MNG: O365 PowerBi Pro (==> GROUP: o365powerbipro) (poznámka: jedná se de-facto o self skupinu, ale nikdo k ní nemá přístup na přihlášení se do ní)
Nelze kombinovat studentskou a zaměstnaneckou licenci (body (1) a (2)), studentská má vždy přednost.
Role v midPointu
GROUP: o365proplus-PRACOVISTE:
- výsledné skupiny pro vyšší licence (A3) pro jednotlivá pracoviště
- automatický výpočet se chytá na název skupiny s prefixem o365proplus- v unix názvu
- indukuje se ze self-management skupin, ale i automaticky
- přiřazení je aktivní pouze pro zaměstnance daného pracoviště
GROUP: o365proplus-students:
- výsledná skupina pro studenty, co mají mít vyšší licenci (A3)
- vyjímky přidatelné v Grouperu ve skupině mng:o365StudentSpecial
GROUP: gapps:
- výsledná skupina pro speciální případy pro standardní licence (A1)
- řídí se jí Google Apps i Microsoft 365
GROUP: office365:
- XXX: zřejmě historická již nepoužívaná skupina
SELF: O365 XXX:
- skupiny, kam se lze přihlásit přes self-management
- obsahuje IdM atribut requestableGroups, který obsahuje seznam vyžadovaných skupin v LDAPu, aby se šlo do skupiny přihlásit (vč. negací)
- indukuje se dál do hlavních skupin, ale s hlídáním příslušností
SELF: gapps:
- skupina, kam se lze přihlásit hostovským kontem nebo aktivním kontem s běžící expirační dobou (A2-A4)
- obsahuje IdM atribut requestableGroups, který povolí takováto konta
- XXX: pro uživatele trochu matoucí název, jako by tam měli být všichni s přístupy, ale slouží jen pro A2 konta
MNG: O365 XXX:
- stejný princip jako SELF: O365 XXX, self-management je vidí, ale nelze se do ní přihlásit
- liší se prázdným atributem requestableGroups
- zvolen jiný název, aby se nepletlo s běžnými self-management skupinami (název je vidět jen interně v midPointu)
Skripty
Počáteční import (aktualizovaný):
# === studenti ===
./group.sh o365proplus-students "Licence Microsoft pro všechny studenty"
arch_student="$(./query-archetype.py identifier=student --oid)"
arch_doktorand="$(./query-archetype.py identifier=doktorand)"
group="$(./query-role.py identifier=o365proplus-students --oid)"
for fak in fdu fst fel fav fpe fek ff fzs fpr; do
./modify-role.py -q archetypeRef@="$arch_student" extension/ext:GROUP_ZKRATKA="${fak^^}" -a "$group":role
./modify-role.py -q archetypeRef@="$arch_doktorand" extension/ext:GROUP_ZKRATKA="${fak^^}" -a "$group":role
done
# === per fakulta ===
# 1) self role
for fak in fdu fst fel fav fpe fek ff fzs rek-ntc rek-civ rek-ps rek-uk rek-ujp rek-rek rek-skm rek-suz rek-uts; do
FAK=${fak^^}
FAK=$(echo $FAK | tr '-' '/')
org=$(echo $fak | cut -d - -f2)
ORG=${org^^}
./create-role.py "name=SELF: O365 $FAK" displayName="o365proplus-$fak" description="Licence pro Microsoft365 (A3plus) - $ORG" extension/ext:requestableGroups=staff requestable=true -a "$(./query-archetype.py name='ZCU Self Management Role' --oid):archetype"
done
# tune catchall REK
rekoid="$(./query-role.py name='SELF: O365 REK/REK' --oid)"
./modify-role.py --oid $rekoid 'extension/ext:requestableGroups+=!civ'
./modify-role.py --oid $rekoid 'extension/ext:requestableGroups+=!ps'
./modify-role.py --oid $rekoid 'extension/ext:requestableGroups+=!suz'
./modify-role.py --oid $rekoid 'extension/ext:requestableGroups+=!uk'
# special
fak=special; FAK=${fak^^}; org=$fak; ORG=$FAK;
./create-role.py "name=MNG: O365 $FAK" displayName="o365proplus-$fak" description="Licence pro Microsoft365 (A3plus) - $ORG" extension/ext:requestableGroups+=nobody requestable=false -a "$(./query-archetype.py name='ZCU Self Management Role' --oid):archetype"
#./query-org.py extension/ext:OU_ZKRATKA=$FAK 'subtype=hr-org-str' | head -n 3
##==> OID
#oid=
#./modify-org.py --oid $oid -i role-group-o365proplus-${fak}:role
# 2) output roles (groups)
for fak in fdu fst fel fav fpe special; do
ORG=${fak^^}
./create-role.py name="GROUP: o365proplus-$org" subtype=group description="Licence Microsoft pro zaměstnance $ORG" displayName="GROUP: o365proplus-$org" identifier="o365proplus-$org" -a $(./query-role.py --oid name="ZCU: Posix Group"):role -a $(./query-archetype.py --oid name="MidPoint: Legacy Group"):archetype
done
ORG=REK; ./create-role.py name="GROUP: o365proplus-$org" subtype=group description="Licence Microsoft pro zaměstnance $ORG" displayName="GROUP: o365proplus-$org" identifier="o365proplus-$org" -a $(./query-role.py --oid name="ZCU: Posix Group"):role -a $(./query-archetype.py --oid name="MidPoint: Legacy Group"):archetype
# 3) self / output connections
for fak in fdu fst fel fav fpe special; do
./modify-role.py --oid role-self-o365proplus-$fak -a role-group-o365proplus-${fak}:role
done
rekgroupoid=$(./query-role.py "name=GROUP: o365proplus-rek" --oid)
for org in ntc civ ps uk ujp rek skm suz uts; do
rekorgoid=$(./query-role.py name="SELF: O365 REK/$ORG" --oid)
./modify-role.py --oid "$rekorgoid" -a "$rekgroupoid":role
done
Ručně přidat do každé self-management role pro assignment výstupní role (dodatečná kontrola při rušení autorizace):
<condition>
<source>
<path>$source/name</path>
</source>
<source>
<path>$source/extension/requestableGroups</path>
</source>
<expression>
<script>
<relativityMode>absolute</relativityMode>
<code>
return zcuUtils.execute('authRequestable', [
'userObj': focus,
'roleName': name,
'requestableGroup': requestableGroups,
]);
</code>
</script>
</expression>
</condition>
CA
# C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root G2 keytool -importcert -keystore ./keystore.jceks -file /usr/share/ca-certificates/mozilla/DigiCert_Global_Root_G2.crt -alias digicert-g2 # C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA keytool -importcert -keystore ./keystore.jceks -file /usr/share/ca-certificates/mozilla/DigiCert_Global_Root_CA.crt -alias digicert-ca
(starší postup byl: https://www.microsoft.com/pki/mscorp/cps/default.htm + import např. M$ CA1, CA2, CA4 a CA5)
Postupy
Hostovská konta
Postup přidání přístupu pro hostovská konta:
- přidělit CRO ID, viz LPS:IdM/midPoint#Přidělení CRO ID
- zařadit do role SELF: gapps (nastaví Google Apps a licenci pro Office365, Office365 to automaticky přiřadí)
Vyrobení licence
Ručně spravované nebo self-management licence lze zakládat bez nutnosti modifikace workflow kódu v midPointu. Takto lze řešit pouze licence, co se nepočítají dynamicky a je to bez závislostí mezi ostatními licencemi.
Postup:
# název k nalezení v admin sekci M365: Billing -> Licences name="Project Plan 3 Faculty" documentation="https://rt.zcu.cz/rt/Ticket/Display.html?id=..." display=o365-projectplan-faculty ./create-role.py -a $(./query-archetype.py name='ZCU Self Management Role' --oid):archetype:org:default "name=MNG: O365 $name" displayName="$display" description="Licence pro Microsoft365 ($name)" documentation="$documentation" extension/ext:requestableGroups=nobody requestable=false
Přidat sekci: (kde ... je název licence z Graph API, k nalezení v organizační struktuře licencí)
<inducement>
<focusMappings>
<mapping>
<name>License</name>
<authoritative>true</authoritative>
<strength>strong</strength>
<expression>
<value>...</value>
</expression>
<target>
<path>$focus/extension/office365Licenses</path>
</target>
</mapping>
</focusMappings>
</inducement>
License PowerBi Pro
Řídí se v IdM rolí MNG: O365 PowerBi Pro. Lze nastavit v assignments přímo v IdM nebo přes příkazový řádek.
Přidání přes příkazová řádek (nahradit $LOGIN za login):
./modify-user.py -q name=$LOGIN --assign "$(./query-role.py 'name=MNG: O365 PowerBi Pro' --oid)":role
Odebrání přes příkazový řádek (nahradit $LOGIN za login):
./modify-user.py -q name=$LOGIN --unassign "$(./query-role.py 'name=MNG: O365 PowerBi Pro' --oid)":role
Přidání fakulty - studenti
(Viz počáteční skripty výše. Toto je výcuc.)
Následující postup dělá:
- přidání GLOBAL: Studenti $FAK do skupiny GROUP: o365proplus-students
- přidání GLOBAL: Doktorandi $FAK do skupiny GROUP: o365proplus-students
# fak=fak
fak=...
arch_student="$(./query-archetype.py identifier=student --oid)"
arch_doktorand="$(./query-archetype.py identifier=doktorand --oid)"
group="$(./query-role.py identifier=o365proplus-students --oid)"
./modify-role.py -q archetypeRef@="$arch_student" extension/ext:GROUP_ZKRATKA="${fak^^}" -a "$group":role
./modify-role.py -q archetypeRef@="$arch_doktorand" extension/ext:GROUP_ZKRATKA="${fak^^}" -a "$group":role
# kontrola
./query-all-references.sh "$group":role
Přidání fakulty - zaměstnanci
(Viz počáteční skripty výše. Toto je výcuc.)
Následující postup dělá:
- vyrobení role SELF: O365 $FAK se správnými requestableGroups
- vyrobení skupiny GROUP: o365proplus-$org
- přiřazení self role do skupiny s dodatečnou podmínkou
fak=...
FAK=${fak^^}
FAK=$(echo $FAK | tr '-' '/')
org=$(echo $fak | cut -d - -f2)
ORG=${org^^}
# self role
./create-role.py "name=SELF: O365 $FAK" displayName="o365proplus-$fak" description="Licence pro Microsoft365 (A3plus) - $ORG" extension/ext:requestableGroups=$fak requestable=true -a "$(./query-archetype.py name='ZCU Self Management Role' --oid):archetype"
self="$(./query-role.py name="SELF: O365 $FAK" --oid)"
./modify-role.py --oid "$self" extension/ext:requestableGroups+=staff
# output group
./group.sh "o365proplus-$org" "Licence Microsoft pro zaměstnance $ORG"
self="$(./query-role.py name="SELF: O365 $FAK" --oid)"
group="$(./query-role.py name="GROUP: o365proplus-$fak" --oid)"
./modify-role.py --oid "$self" -a "$group":role
...a pak ruční přidání podmínky assignmentu v "SELF: O365 $ORG", viz výše.
Přidání A3 licence jednomu uživateli
Dá se nakliknout v GUI.
Nebo postup z řádky ($login je login uživatele, SELF: O365 FPR je název role podle fakulty/pracoviště):
oidRole="$(./query-role.py name='SELF: O365 FPR' --oid)" ./modify-user.py -q name=$login -a $oidRole:role
Issues
- po založení uživatele následný get selže, protože uživatel se objeví až po delší době
- obchází se na úrovni konektoru správnou reakcí na chyby a tolerantnějším nastavením reakcí na chyby v midPointu
- konflikt mezi skupinami a osobami kvuli e-mailové adrese
- čas od času se nějaká identita nezaloží