Title Text

Ny integrasjon mellom SAP og UA

Sten Solli  : USIT / ITI / APP

Title Text

Universitetets Adgangskontrollsystem = Lenel OnGuard

Title Text

Personer = Kortholdere

Title Text

Alt ligger i en database

Title Text

Det meste er tilgjenglig via WMI

Vi lager noe mellom OnGuard WMI / servicer og IntArk MQ / kildesystem API

MQ

UA

SAP

API GW

integrasjon@usit.uio.no

UA

# Pika is a python library for AMQP-0-9-1 (RabbitMQ)
import pika


# Set the connection parameters to connect to rabbit-server 
credentials = pika.PlainCredentials(bah, kanin)
parameters = pika.ConnectionParameters(host='mq.uio.no', port=5671,virtual_host='/no/uio/integration',
    ssl=True,ssl_options=dict(ssl_version=ssl.PROTOCOL_TLSv1), credentials=credentials)
connection = pika.BlockingConnection(parameters)
channel = connection.channel() #'/no/uio/ua/test')

channel.basic_qos(prefetch_count=1)
channel.basic_consume(callback, queue='q_sap_onguard')


# Start listening on queue
channel.start_consuming()

Begynner å lytte på riktig kø i MQ:

MQ

UA

En melding kommer:

Received b'{"sub":"https://api-gateway.uio.no/sws/v2/employees(11009182)",
    "urn:ietf:params:event:SCIM:modify":{"attributes":["privateMobile"]},
    "eventUris":["urn:ietf:params:event:SCIM:modify"],"iss":"sap",
    "jti":"005056a9-4531-1ee9-88f3-818393c954bb","iat":1548752473,"aud":[]}'
def callback(ch, method, properties, body):
    global lasturl, file, url 
    sapurl ="https://api-gateway.uio.no/sws/v2/employee"
    time.sleep(body.count(b'.'))
    body = body.decode("utf-8")
    url = util.geturi(body)
    if url == lasturl: pass 
    else: 
      if url.startswith(sapurl,0,len(sapurl)):
        getsapdata(url)
    ch.basic_ack(delivery_tag = method.delivery_tag)
    lasturl = url 

Er dette et attributt vi bryr oss om? Da behandler vi meldingen videre:

UA

SAP

API GW

#API bibliotek
import requests

def getsapdata(url):

  assignments = {}
  assurl = url + '/assignments'

  # Henter data fra API 
  response = requests.get(url, headers=headers) 
  assign = requests.get(assurl, headers=headers) 
  util.loggline('nresponse.status_code = ' + str(response.status_code) )
  
  # 200 = kontakt suksess (html)
  if response.status_code == 200:
    ansatt = getSAPAnsatt(response.text)

Henter data fra SAP API:

 {'firstName': "Luke", 'lastName': "Skywalker", 'workEmail': "lukesk@usit.uio.no", 
    'norwegianIdentificationNumber': '1212120986', 'pid': '12121209862', 
    'employmentStatus': "active", 'personId': '19120400', 'hireDate': "2019-01-01", 
    'locationCode': None, 'passportIssuingCountry': None, 'passportNumber': None, 
    'kontakttelefon': "73782922"}

Får litt JSON til slutt:

### Henter Employeedata fra xml
def sapEmployed(prop):
  temp = prop.find('d:firstName', ns)
  firstName = setValue(temp)
  loggline(firstName+"\n")
  temp = prop.find('d:lastName', ns)
  lastName = setValue(temp)
  temp = prop.find('d:privateMobile', ns)
  privateMobile = setValue(temp)
  temp = prop.find('d:workEmail', ns)
  workEmail = setValue(temp)
  temp = prop.find('d:norwegianIdentificationNumber', ns)
  norwegianIdentificationNumber = setValue(temp)
  temp = prop.find('d:employmentStatus', ns)
  employmentStatus = setValue(temp)
  temp = prop.find('d:personId', ns)
  personId = setValue(temp)
  temp = prop.find('d:hireDate', ns)
  hireDate = setValue(temp)
  temp = prop.find('d:locationCode', ns)
  locationCode = setValue(temp)
  temp = prop.find('d:workPhone', ns)
  workPhone = setValue(temp)
  temp = prop.find('d:workMobile', ns)
  workMobile = setValue(temp)
  phone = setPhone(workMobile,privateMobile,workPhone)
  temp=prop.find('d:passportIssuingCountry')
  passportIssuingCountry=setValue(temp)
  temp=prop.find('d:passportNumber')
  passportNumber=setValue(temp)
  ### PID = pnummer i OnGuard 
  pid = str(norwegianIdentificationNumber)+"2"
  
  ansatt = {'firstName': firstName, 
    'lastName' : lastName, 
    'workEmail': workEmail,
    'norwegianIdentificationNumber': norwegianIdentificationNumber,
    'pid': pid,
    'employmentStatus' : employmentStatus, 
    'personId' : personId,
    'hireDate': hireDate,
    'locationCode': locationCode,
    'passportIssuingCountry': passportIssuingCountry,
    'passportNumber': passportNumber,
    'kontakttelefon':phone 
    }  
  return ansatt
def getSAPAnsatt(xmldata):
    ansatt = {}
    ### Som XML 
    root = ElementTree.fromstring(xmldata)
    ### Hente employee data fra SAP
    for emp in root:
      for prop in emp:   
        ansatt = util.sapEmployed(prop)
    if ansatt is not None:
      return ansatt 
    else: 
      return None 

UA

OnGuard

onguarduser = wmihelper.getSAPCardholder(ansatt['pid'])
if onguarduser is not None:
    updateSAPCardholder(ansatt,onguarduser)
else: 
    newSAPCardholder(ansatt)

Vi oppdaterer eller lager OnGuard kortholder:


def updateSAPCardholder(ansatt, onguarduser):    
    try: 
      if ansatt["firstName"] is not None: onguarduser = wmihelper.setWMIfnavn(onguarduser,ansatt)
      if ansatt["lastName"] is not None:  onguarduser = wmihelper.setWMIenavn(onguarduser,ansatt)
      if ansatt["workEmail"] is not None: onguarduser = wmihelper.setWMIepost(onguarduser,ansatt)
      if ansatt["personId"] is not None: onguarduser = wmihelper.setWMIansattnr(onguarduser,ansatt)
      if ansatt["kontakttelefon"] is not None:
          if str(ansatt["kontakttelefon"]).isdigit():onguarduser =  wmihelper.setWMIphone(onguarduser,ansatt)
      if ansatt["passportIssuingCountry"] is not None: instance.HOMEADR3 = ansatt["passportIssuingCountry"]
      if ansatt["passportNumber"] is not None: instance.HOMEADR4 = ansatt["passportNumber"]
      if ansatt["locationCode"] is not None: onguarduser =  wmihelper.setWMIsted(onguarduser,ansatt)
      if wmifrom is not None: onguarduser =  wmihelper.setWMIfromdate(onguarduser,ansatt,wmifrom)
      if wmitil is not None: onguarduser = wmihelper.setWMItodate(onguarduser,ansatt,wmitil)
      # Assignement variables
      if ansatt["locationId"] is not None:
          onguarduser =  wmihelper.setWMIlocation(onguarduser,ansatt) 
          ## Kalle på funksjon som legger/fjerner tilganger basert på denne infoen
      if ansatt["jobTitle"] is not None:
          onguarduser =  wmihelper.setWMItitle(onguarduser,ansatt) 
          ## Kalle på funksjon som legger/fjerner tilganger basert på denne infoen

Her vil vi gjøre logikk for å behandle adgangsrettigheter automatisk

MQ

UA

Noen systemer vil vite når personer får nye adgangskort:

#Bruker igjen Pika biblioteket
import pika

lenel = wmi.WMI(moniker='//./root/OnGuard')  
evtsrc = lenel.ExecNotificationQuery("SELECT * FROM __InstanceModificationEvent WHERE (TargetInstance ISA 'Lnl_Badge')" ) 

while True:
  try: 
      badge = wmi.WMI(wmi=evtsrc.NextEvent(15000))
      changedBadge = wmi.WMI(wmi=onguard.get_wmichange(badge) )
      userID = str(changedBadge.PERSONID)
      user = onguard.UserFromBadge(userID)
      sted = onguard.getStedForUser(user)     
      rabbitmelding = {'timestamp':badge.TIME_CREATED, 'change' : 'Badge','sted':sted,'URL':'toCome'}

  dictionaryToJson = json.dumps(rabbitmelding)

  credentials = pika.PlainCredentials(humbug, kanin)
  parameters = pika.ConnectionParameters(host='mq.uio.no', port=5671, virtual_host='/no/uio/ua/test',ssl=True, 
               credentials=credentials)

  connection = pika.BlockingConnection(parameters)
  channel = connection.channel() 
  channel.queue_declare(queue='q_onguard', durable=True)

  result = channel.basic_publish(exchange='ex_uatest',
                      routing_key='badge.info',
                      body =dictionaryToJson,
                      mandatory=True
                      )                  

  connection.close()

Title Text

Vi skal:

  • Oppdatere og lage nye datafelt i OnGuard
  • Vaske data om ansatte
  • Prodsette sync med SAP
  • Vaske data om studenter
  • Prodsette sync med FS

UA og IntArk

By Sten Solli

UA og IntArk

Hvordan UiO IntArk brukes i UA. Kick off ITI 3.4.

  • 1,134