Pifu IMS MA
Management Agent for PIFU IMS
Type: ECMA 2.2
Versjonsnummer: 1.4.0
Dato: 05.02.2019
Målsystem Versjon: 1.4.0
Objecttyper: person, group, membershipgroup, orgLevel#1(orgunit), orgLevel#0(organization)
Beskrivelse
Management agenten henter data på PIFU IMS-format fra xml-fil. Xml-filen blir generert i forkant av selve PIFU MA-kjøringen. Agenten støtter import både fra SATS og Extens. Siden det ikke finnes noen generelle IST-støttede metoder for å skrive tilbake data til SATS/Extens, er det ikke implementert eksport for denne agenten.
Hvilke PIFU IMS-attributtene som importeres til CS, styres av filen CSAttributes.json som ligger i MaData-mappen for agenten. Dersom agenten heter PIFU MA må filen ligge i mappen "C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\MaData\PIFU MA". Eksempelfil ligger i install-mappen sammen med xml for agenten
En fullstendig oversikt med alle attributter som er tilgjengelig i uttrekket for de forskjellige objekttypene, finner man i starten av log-filen(se under). Det er totalt ca 670 attributter(!) så det er ikke å anbefale å ta med alle.
Full import File Path Fullstendig sti fil input-filen. For eksempel c:\pifu\pifudata.xml
Use PersonCode as person-id Huk av denne hvis en annen identifikator enn fødselsnummer ønskes benyttet som anker for person. For SATS er det da Person-feltet som brukes, for Extens brukes Webbrukerid.
Dagens Buddy benytter fødselsnummer som anker. Dersom dette endres (for eksempel ved bytte fra midlertidig fødselsnummer til ekte fødslesnummer), blir det opprettet et nytt personobjekt i CS og det gamle objektet slettet med de problemer det medfører: ny brukerident, den gamle deaktivert osv.
Verdien i Person-feltet i SATS er unik, blir ikke gjenbrukt og endres ikke. Person-feltet derfor en god kandidat som anker. Ved endring i fødselsnummer vil personen fremdeles ha samme CS-objekt og det skjer ingen endring av brukerident.
Webbrukerid i Extens er unik og uavhengig av fødselsnummerendringer, men dessverre er det mulig å endre denne. I følge IST finnes ikke noe varig og unikt felt i Extens, webbrukerid er det nærmeste man kommer. Extensfylkene må selv vurdere om de vil bruke fødselsnummer eller webbrukerid som anker.
Enable Validation (validates before parsing)
Huk av denne for å sjekke at uttrekket er gyldig xml og i henhold til xml-skjemaet for PIFU IMS. Det anbefales å slå av valideringen hos IST via uttrekkskommandoen (se PIFU IMS uttrekk fra Extens/Sats), og heller validere uttrekket ved å huke av her.
Parametre for gruppegenerering
Under Global Parameters er det mulig å konfigurere hvilke gruppetyper som skal genereres. PIFU MA-en kan generere to hovedvarianter av grupper: Group og Membership group.
Group
Avhukingen under vil generere de samme gruppetypene som kom fra ABC Enterprise:
Membership group
Avhukingen under vil generere alle elever-gruppe, alle lærere-gruppe og alle ansatte-gruppe for hele organisasjonen, og tilsvarende for hver skole:
Logging
Logging fra agenten konfigureres i fila log.config som ligger i mappen "C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\MaData\PIFU MA". Standard er at logging skjer til mappen "C:\Logs\VIGOBAS\Pifu MA".
Validering
Det er to vanlige feil i xml-uttrekket. Den ene er tegn som er ugyldige i xml, for eksempel i epost-adresser. Når validering er slått på for agenten, vil en slik feil få kjøringen til å stoppe umiddelbart. Det logges en feil i Windows Application-loggen med event ID 6801:
The extensible extension returned an unsupported error.
The stack trace is:
"System.Xml.XmlException: '', hexadecimal value 0x1F, is an invalid character. Line 253322, position 21.
Det er laget et lite CLI-program CleanXML.exe som finner alle ugyldige tegn i uttrekket, fjerner feilene og skriver linjene med feil til en logg-fil. CleanXML.exe ligger i installmappen til PIFU-agenten.
Bruk: CleanXML <sti til input og output-fil> <input-fil: fil som skal renses> <output-fil: fil med renset xml>
Loggfil er error.txt og ligger i samme mappe som input og output-filene. I Notepad++ ser man de ugyldige tegnene:
Den andre feilen er ugyldige eller manglende data i henhold til xml-skjemaet for PIFU IMS. Valideringen på agenten vil finne alle slike feil i uttrekket og så stoppe før selve kjøringen. Fim-ma-debug.txt inneholder feilene:
Warning : The XML file did not validate due to
Error: Validation error on line : 10931920 position : 30. msg : The 'http://pifu.no/xsd/pifu-ims_sas/pifu-ims_sas-1.1:begin' element is invalid
- The value '' is invalid according to its datatype 'Date' - The string '' is not a valid Date value.
Error: Validation error on line : 10931959 position : 30. msg : The 'http://pifu.no/xsd/pifu-ims_sas/pifu-ims_sas-1.1:begin' element is invalid
- The value '' is invalid according to its datatype 'Date' - The string '' is not a valid Date value.
Feilene logges også i Windows Application-loggen med event ID 6801.
Ved å gå inn i uttrekksfilen - xml-editoren foxe kan anbefales - kan man finne linjer som feiler, og hvilken person eller gruppe som feilen(e) er knyttet til.
Flow
Der hvor det ikke ligger noe MV-attributt. er det ikke satt opp noen direkteflyt i MA-en. Men CS-attributtet er tilgjengelig, og kan være benyttet i en avansert flyt. Tabellene inneholder de attributtene som blir hentet inn i CS dersom man benytter CSAttributes.sjon-eksempelfilen.
Person
Import
CS Object Type | CS Attribute | Mapping Type | MV Object Type | MV Attribute | Advanced Rule |
---|---|---|---|---|---|
person | EduPersonEntitlement | Direct | person | eduPersonEntitlement | |
person | EnhetUserType | Direct | person | enhetUserType | |
person | ID | Direct | person | basSASID | |
person | MemberOf@orgLevel#0 | Direct | person | basOrgRef | |
person | MemberOf@orgLevel#1 | Direct | person | eduPersonOrgUnitDN | |
person | personMobilePrivate | Direct | person | mobile | |
person | personPostalAddressPrivate.locality | Direct | person | ||
person | personPostalAddressPrivate.pcode | Direct | person | ||
person | personPostalAddressPrivate.street | Direct | person | ||
person | personTelephonePrivate | Direct | person | homePhone | |
person | pifuXml#demographics.bday | Direct | person | basBirthDate | |
person | pifuXml#demographics.gender | Direct | person | ||
person | pifuXml#email | Direct | person | ||
person | pifuXml#name.fn | Direct | person | displayName | |
person | pifuXml#name.n.family | Direct | person | lastName | |
person | pifuXml#name.n.given | Direct | person | firstName | |
person | primaryOrgUnit | Direct | person | eduPersonPrimaryOrgUnit | |
person | primaryClassGroup | Direct | person | ||
person | primaryRole | Direct | person | eduPersonPrimaryAffiliation | |
person | Roles | Direct | person | eduPersonAffiliation | |
person | ssn | Direct | person | basSSN | |
person | ssnValidation | Direct | person | basSSNValidation | |
person | studentID | Direct | person | ||
person | workforceID | Direct | person | ||
person | pifuXml#demographics.bday | Advanced | person | basBirthDate | PifuMA_formatBirthDate |
person | enhetUserType | Advanced | person | department | PifuMA_enhetUserTypeToDepartment |
Avanserte flytregler
PifuMA_formatBirthDate
import datetime
from datetime import *
date = datetime.strptime(source['pifuXml#demographics.bday'].Value, '%d.%m.%Y %H:%M:%S')
target['basBirthDate'].Value = date.strftime('%Y-%m-%d')
PifuMA_enhetUserTypeToDepartment
# -*- coding: utf-8 -*-
import string
import clr
clr.AddReference('System.Data')
from System.Data.SqlClient import SqlConnection, SqlParameter
conn_string = 'data source=localhost; initial catalog=FIMSynchronizationService; trusted_connection=True'
command_txt ="select displayName FROM mms_metaverse WITH (nolock) WHERE(basUniqeID = @orgunit_id and object_type='organizationalUnit')"
target['department'].Delete()
enhetUserTypes = dict(e.ToString().split(';') for e in source['enhetUserType'].Values)
if target['eduPersonPrimaryAffiliation'].IsPresent:
primaryRole = target['eduPersonPrimaryAffiliation'].Value
if primaryRole in enhetUserTypes:
primaryOrgUnit= enhetUserTypes[primaryRole]
connection = SqlConnection(conn_string)
connection.Open()
command = connection.CreateCommand()
command.CommandText = command_txt
command.Parameters.Add(SqlParameter('orgunit_id', primaryOrgUnit))
reader = command.ExecuteReader()
if reader.HasRows:
reader.Read()
department= reader['displayName']
target['department'].Value = department
connection.Close()
Group
Import
CS Object Type | CS Attribute | Mapping Type | MV Object Type | MV Attribute | Advanced Rule |
---|---|---|---|---|---|
group | grepcode | Direct | group | ||
group | grepcodeShortForm | Direct | group | ||
group | groupType | Direct | group | type | |
group | groupTypeAsString | Direct | group | ||
group | ID | Direct | group | basUniqueID | |
group | MemberOf@orgLevel#0 | Direct | group | ||
group | MemberOf@orgLevel#1 | Direct | group | ||
group | MemberRole.Learner | Direct | group | member | |
group | MemberRole.Instructor | Direct | group | ||
group | Members | Direct | group | ||
group | pifuXml#description.short | Direct | group | ||
group | pifuXml#description.long | Direct | group | ||
group | pifuXml#description.full | Direct | group | ||
group | schoolName | Direct | group | ||
group | RoleType | Direct | group | ||
group | groupType, pifuXml#description.short, pifuXml#description.long, schoolName | Advanced | group | displayName | PifuMA_displayNameGroup |
Avanserte flytregler
PifuMA_displayNameGroup
if source['groupType'].Value == '4':
target['displayName'].Value = source['pifuXml#description.short'].Value
elif source['groupType'].Value == '5':
target['DisplayName'].Value = 'Programområdet ' +source['pifuXml#description.short'].Value + ' ved ' + source['schoolName'].Value
elif source['groupType'].Value == '6':
target['displayName'].Value = 'Utdanningsprogrammet ' +source['pifuXml#description.short'].Value + ' ved ' + source['schoolName'].Value
elif source['groupType'].Value == '7':
target['displayName'].Value = 'Faget ' +source['pifuXml#description.long'].Value + ' ved ' + source['schoolName'].Value
else:
target['displayName'].Value = source['pifuXml#description.long'].Value
MembershipGroup
Import
CS Object Type | CS Attribute | Mapping Type | MV Object Type | MV Attribute | Advanced Rule |
---|---|---|---|---|---|
membershipGroup | grepcode | Direct | group | ||
membershipGroup | grepcodeShortForm | Direct | group | ||
membershipGroup | ID | Direct | group | basUniqueID | |
membershipGroup | MemberOf@orgLevel#0 | Direct | group | ||
membershipGroup | MemberOf@orgLevel#1 | Direct | group | ||
membershipGroup | Members | Direct | group | member | |
membershipGroup | pifuXml#description.short | Direct | group | ||
membershipGroup | pifuXml#description.long | Direct | group | ||
membershipGroup | pifuXml#description.full | Direct | group | description | |
membershipGroup | schoolName | Direct | group | ||
membershipGroup | RoleType | Direct | group | ||
membershipGroup | Advanced | group | type | Constant: 'MembershipGroup' | |
membershipGroup | membershipGroupType, pifuXml#description.short, pifuXml#description.long, schoolName | Advanced | group | displayName | PifuMA_displayNameMembershipGroup |
Avanserte flytregler
PifuMA_displayNameMembershipGroup
if source["RoleType"].Value == 'Learner':
target["DisplayName"].Value = "Alle elever ved " + source["pifuXml#description.short"].Value
if source["RoleType"].Value == 'Instructor':
target["DisplayName"].Value = "Alle lærere ved " + source["pifuXml#description.short"].Value
if source["RoleType"].Value == 'Member':
target["DisplayName"].Value = "Alle administrativt ansatte ved " + source["pifuXml#description.short"].Value
orgLevel#1 (OrgUnit)
Import
CS Object Type | CS Attribute | Mapping Type | MV Object Type | MV Attribute | Advanced Rule |
---|---|---|---|---|---|
orgLevel#1 | ID | Direct | organizationUnit | basUniqueID | |
orgLevel#1 | orgEmail | Direct | organizationUnit | ||
orgLevel#1 | organizationNumber | Direct | organizationUnit | basOrgUnitNumber | |
orgLevel#1 | pifuXml#description.short | Direct | organizationUnit | basParentOrgUnitRef | |
orgLevel#1 | pifuXml#description.long | Direct | organizationUnit | displayName | |
orgLevel#1 | MemberOf@orgLevel#0 | Direct | organizationUnit | description | |
orgLevel#1 | VigoNumber | Direct | organizationUnit | basVigoNumber |
orgLevel#0 (Organization)
Import
CS Object Type | CS Attribute | Mapping Type | MV Object Type | MV Attribute | Advanced Rule |
---|---|---|---|---|---|
orgLevel#0 | ID | Direct | organization | basUniqueID | |
orgLevel#0 | organizationNumber | Direct | organization | basOrgNumber | |
orgLevel#0 | pifuXml#description.full | Direct | organization | description | |
orgLevel#0 | pifuXml#description.short | Direct | organization | displayName | |
orgLevel#0 | pifuXml#description.short | Direct | organization | basOrgLegalName | |
orgLevel#0 | Advanced | organization | Constant: 'postmottak@buddy.no' |
PIFU IMS-uttrekk
Siste versjon av PIFU-IMS er lagt ut på følgende lenke.
Person
<person>
<sourcedid>
<source>akershus-fk.no</source>
<id>01010199999</id>
</sourcedid>
<userid useridtype="personNIN">03020199999</userid>
<userid useridtype="username">KANO52</userid>
<userid useridtype="studentID">739020</userid>
<name>
<fn>Kari Norkvinne</fn>
<n>
<family>Norkvinne</family>
<given>Kari</given>
</n>
</name>
<demographics>
<gender>1</gender>
<bday>2001-02-03</bday>
</demographics>
<email>karino@gmail.com</email>
<tel teltype="1">+4755443322</tel>
<tel teltype="3">+4799887766</tel>
<adr>
<street>Oppegårdveien 700</street>
<locality>LANGHUS</locality>
<pcode>1405</pcode>
</adr>
<extension>
<pifu_email type="personEmailPrivate">karino@gmail.com</pifu_email>
<pifu_tel type="personTelephonePrivate">+4755443322</pifu_tel>
<pifu_tel type="personMobilePrivate">+4799887766</pifu_tel>
<pifu_adr type="personPostalAddressPrivate">
<adr>
<street>Oppegårdveien 700</street>
<locality>LANGHUS</locality>
<pcode>1405</pcode>
</adr>
</pifu_adr>
</extension>
</person>
Group
I PIFU-IMS benyttes group-objekter til å modellere både organisasjon(skoleeier), organisasjonsenhet(skole) og "normale" skolegrupper som basisgrupper, kontaktlæergrupper og undervisningsgrupper. Også grep-kodene som er obligatorisk/anbefalt i Feide 1.6 (trinn, utdanningsprogram, programområde og fag) har egne gruppeobjekter.
Organisasjon (skoleier)
Denne gruppetypen legges inn i CS som orgLevel#0-objekt
<group>
<sourcedid>
<source>akershus-fk.no</source>
<id>02</id>
</sourcedid>
<grouptype>
<scheme>pifu-ims-go-org</scheme>
<typevalue level="1">skoleeier</typevalue>
</grouptype>
<description>
<short>Akershus fylkeskommune</short>
</description>
<relationship relation="1">
<sourcedid>
<source>akershus-fk.no</source>
<id>02</id>
</sourcedid>
<label>Akershus fylkeskommune</label>
</relationship>
<extension>
<pifu_id type="organizationNumber">
<pifu_value>958381492</pifu_value>
<pifu_scope>Enhetsregisteret</pifu_scope>
<pifu_unique>1</pifu_unique>
</pifu_id>
<pifu_id type="countyNumber">
<pifu_value>02</pifu_value>
<pifu_scope>http://hotell.difi.no/?dataset=difi/geo/fylke</pifu_scope>
<pifu_unique>0</pifu_unique>
</pifu_id>
</extension>
</group>
organisasjonsenhet(skole)
Denne gruppetypen legges inn i CS som orgLevel#1-objekt
<group>
<sourcedid>
<source>akershus-fk.no</source>
<id>02023</id>
</sourcedid>
<grouptype>
<scheme>pifu-ims-go-org</scheme>
<typevalue level="2">skole</typevalue>
</grouptype>
<description>
<short>Ski videregående skole</short>
</description>
<relationship relation="1">
<sourcedid>
<source>akershus-fk.no</source>
<id>02</id>
</sourcedid>
<label>Akershus fylkeskommune</label>
</relationship>
<extension>
<pifu_id type="organizationNumber">
<pifu_value>974587696</pifu_value>
<pifu_scope>Enhetsregisteret</pifu_scope>
<pifu_unique>1</pifu_unique>
</pifu_id>
<pifu_id type="vigoNumber">
<pifu_value>02023</pifu_value>
<pifu_scope>vigo</pifu_scope>
<pifu_unique>1</pifu_unique>
</pifu_id>
<pifu_name type="name">
<pifu_value>Ski videregående skole</pifu_value>
</pifu_name>
<pifu_email type="orgEmail">post@ski.vgs.no</pifu_email>
<pifu_url type="orgURL">http://www.ski.vgs.no</pifu_url>
<pifu_tel type="orgTelephone">+4764913600</pifu_tel>
<pifu_adr type="orgPostalAddress">
<adr>
<street>Gymnasveien</street>
<locality>SKI</locality>
<pcode>1401</pcode>
</adr>
</pifu_adr>
</extension>
</group>
Basisgruppe
<group>
<sourcedid>
<source>akershus-fk.no</source>
<id>1_1STF_02023</id>
</sourcedid>
<grouptype>
<scheme>pifu-ims-go-grp</scheme>
<typevalue level="1">basisgruppe</typevalue>
</grouptype>
<description>
<short>1STF</short>
<long>SKI:1STF</long>
<full>Basisgruppe 1STF ved Ski videregående skole</full>
</description>
<timeframe>
<begin restrict="0">2016-08-01</begin>
<end restrict="0">2017-06-30</end>
<adminperiod>2016/2017</adminperiod>
</timeframe>
<relationship relation="1">
<sourcedid>
<source>akershus-fk.no</source>
<id>02023</id>
</sourcedid>
<label>Ski videregående skole</label>
</relationship>
<extension>
<pifu_name type="name">
<pifu_value>1STF</pifu_value>
</pifu_name>
<pifu_name type="fullName">
<pifu_value>Basisgruppe 1STF ved Ski videregående skole</pifu_value>
</pifu_name>
</extension>
</group>
Gruppe for trinn
<group>
<sourcedid>
<source>akershus-fk.no</source>
<id>4_VG3_02023</id>
</sourcedid>
<grouptype>
<scheme>pifu-ims-go-grp</scheme>
<typevalue level="4">trinn</typevalue>
</grouptype>
<description>
<short>Ski videregående skole trinn VG3</short>
</description>
<relationship relation="1">
<sourcedid>
<source>akershus-fk.no</source>
<id>02023</id>
</sourcedid>
<label>Ski videregående skole</label>
</relationship>
<extension>
<pifu_id type="grepCode">
<pifu_value>http://psi.udir.no/laereplan/aarstrinn/vg3</pifu_value>
<pifu_scope>grep - levende læreplaner</pifu_scope>
<pifu_unique>0</pifu_unique>
</pifu_id>
</extension>
</group>
Gruppe for utdanningsprogram
<group>
<sourcedid>
<source>akershus-fk.no</source>
<id>5_ID_02023</id>
</sourcedid>
<grouptype>
<scheme>pifu-ims-go-grp</scheme>
<typevalue level="5">utdanningsprogram</typevalue>
</grouptype>
<description>
<short>Idrettsfag</short>
</description>
<relationship relation="1">
<sourcedid>
<source>akershus-fk.no</source>
<id>02023</id>
</sourcedid>
<label>Ski videregående skole</label>
</relationship>
<extension>
<pifu_id type="grepCodeShortForm">
<pifu_value>ID</pifu_value>
<pifu_scope>grep - levende læreplaner</pifu_scope>
<pifu_unique>0</pifu_unique>
</pifu_id>
<pifu_id type="grepCode">
<pifu_value>http://psi.udir.no/ontologi/utdanningsprogram/idrettsfag</pifu_value>
<pifu_scope>grep - levende læreplaner</pifu_scope>
<pifu_unique>0</pifu_unique>
</pifu_id>
</extension>
</group>
Membership
Knytningen mellom person og gruppe uttrykkes i membershipobjekter. Hva slags rolle personen har i denne gruppen er også med(roletype ="02" betyr at vedkommende er elev i denne gruppen).
<membership>
<sourcedid>
<source>akershus-fk.no</source>
<id>1_1STF_02023</id>
</sourcedid>
<member>
<sourcedid>
<source>akershus-fk.no</source>
<id>03020199999</id>
</sourcedid>
<idtype>1</idtype>
<role roletype="02">
<status>1</status>
<timeframe>
<begin restrict="0">2016-08-16</begin>
<end restrict="0">2017-07-31</end>
</timeframe>
</role>
</member>
...
</membership>
Det er bare et membershipobjekt per gruppe, dvs at alle gruppens medlemmer ligger i dette objektet.