ePAS under the hood

Electronic Personnel Attendance System

un sistema di rilevazione delle presenze/assenze del personale dipendente del CNR

ottobre 2021 - Workshop ICTalk@CNR 2021

Cristian Lucchesi, Maurizio Martinelli, Dario Tagliaferri <nome.cognome@iit.cnr.it>

Speranza/Sogno

epas under the hood dream

Realtà

epas under the hood reality

Scopo delle presentazione

  • descrivere l’architettura ed i componenti

  • illustrare le integrazioni con gli altri sistemi CNR

  • mostrare strumenti/framework software utilizzati

    • linguaggi e framework

    • strumenti di CI/CD, di logging e monitoring impiegati

  • spunti e riferimenti per lo sviluppo di soluzioni in-house e/o per estendere ePAS

Diffusione di ePAS

  • ePAS ad oggi è utilizzato da

    • oltre 360 sedi CNR

    • ~7k dipendenti CNR

    • tutto il personale INAF

    • tutto il personale LAMMA

Requisiti funzionali

  • software riutilizzabile da più sedi / istituti / enti di ricerca

  • configurabile per le specificità locali / istituzionali

  • con vincoli e controlli contrattuali stringenti

    • concordati e verificati dall’Ufficio del Personale

  • software dinamico nel tempo

Requisiti tecnici

  • no dipendenze da software commerciali

  • si all’utilizzo di strumenti opensource

  • controllo completo sviluppo e mantenimento con competenze in-house CNR

  • integrato con altre applicazioni CNR as much as possible

  • soluzione scalabile negli utenti e nel tempo

10000 feet view

  • web app centralizzata per l’accesso dei dipendenti

  • REST server centralizzato per la ricezione delle timbrature

  • unico database clusterizzato

  • molti "ePAS client"

    • leggono timbrature da lettori e inviano via REST

  • alcuni proxy/relaying party shibboleth per gestione https e autenticazione centralizzata

Zoom in

  • unico codebase (monolite) per app principale

    • Play framework! Java, JPA/Hibernate, Groovy Template

    • ~72.000 LoC Java

    • ~27.000 LoC Groovy Template/HTML

    • ~2600 LoC Javascript

    • ~9.300 Statement SQL (175 evoluzioni DB)

    • 182 tabelle SQL (metà di storico / Envers)

Zoom in

  • Kraken Listener: ricezione missioni da AMQP ed invio REST

  • Telework-stampings: gestione (REST) dati telelavoro

Zoom in

Lesson learned

  • un solo monolite è difficile da mantenere

    • cambi una virgola in una classe nel package X e muore una oscura feature nel package Y

    • quasi impossibile venirne a capo anche con i test

  • no integrità referenziale con APP diverse

    • necessità di definire bene identificatori entità esterne e API con altre applicazioni

Lesson learned

  • API Versioning fondamentale per mantenimento nel tempo

  • auth e authz sono un delirio in APP distribuite

    • senza un sistema di auth centralizzato (OpenID?) e authz ben definito

Controllo ruoli e permessi

  • ruoli per sede - configurazione self service

  • utilizzo di JBoss Drools - Business Rules Management System (BRMS)

  • basato sull’algoritmo ReTe permette di processare moltissime condizioni in tempi brevissimi

  • integrato (AOP) in ogni chiamata di metodi pubblici

permissions.drl

rule managePersonDayInOffice
when
 $uro: UsersRolesOffices(role.name in ("personDayReader", "restClient"))
 $o: Office() from $uro.office
 $c: PermissionCheck(action in (

        "rest.PersonDays.getDaySituation",
        "rest.PersonDays.getMonthSituation",
        "rest.Persons.peopleList",

        "rest.v2.Certifications.getMonthSituation",
        "rest.v2.Certifications.getMonthSituationByOffice",
        "rest.v2.Certifications.getMonthValidationStatusByOffice",
        "rest.v2.Certifications.getMonthValidationStatusByPerson",

        "rest.v2.PersonDays.getDaySituationByOffice",
        "rest.v2.PersonDays.getMonthSituationByOffice",
        "rest.v2.PersonDays.getDaySituation",

        "rest.v2.ContractWorkingTimeTypes.show",

        "rest.v2.WorkingTimeTypes.show",
        "rest.v2.WorkingTimeTypes.list",

        "rest.v3.PersonDays.getDaySituationByOffice",
        "rest.v3.PersonDays.getMonthSituationByOffice",
        "rest.v3.PersonDays.getDaySituation",
        "rest.v3.PersonDays.getMonthSituationByPerson",
        "rest.v3.PersonDays.offSiteWorkByPersonAndMonth",
        "rest.v3.PersonDays.offSiteWorkByOfficeAndMonth",

        "rest.v2.Contracts.byPerson",
        "rest.v2.Contracts.show",

        "rest.v2.Leaves.byPersonAndYear",
        "rest.v2.Leaves.byOfficeAndYear",
        "rest.v2.Leaves.byOfficeAndYear.show",

        "rest.v3.Vacations.byPersonAndYear",

        "rest.Absences.absencesInPeriod",
        "rest.Absences.attachment"


       ), target == $o, granted == false)
then
 $c.grant();
end
  • circa 140 rule definite

Dati e accessi ne hai?

  • no ePAS click day ePAS (no busta paga day come SIPER :-))

  • utilizzato tutti i giorni da migliaia di dipendenti

  • adesso ~6000 timbrature al giorno da tutta Italia

  • > 7 milioni di timbrature registrate

  • > 10 milioni di rendiconti giornalieri registrati

  • ~500 email inviate al giorno

Dati da Graylog

graylog epas amministrazione

e la scalabilità?

  • nessuna sessione condivisa tra istanze dei server ePAS: sessione lato client

  • possibilità di incrementare i server orizzontalmente

  • il DB può essere l’unico collo di bottiglia

    • non lo è per ora

    • varie tecniche di scalabilità applicabili

      • multimaster, più slave per letture, sharding, etc

Observability (log e notifiche)

  • i log centralizzati in un server Graylog

    • Graylog: opensource, dati su ElasticSearch, interfaccia WEB

    • sono inviati via UDP in formato GELF

  • log di tipo ERROR inviati ad un canale Slack

    • realtime troubleshooting :-)

  • log per richieste lente (oltre 700 ms)

Notifiche log error

epas slack notification error

Observability (metriche)

  • metriche applicative nel formato prometheus logo

  • esportate anche metriche di sistema (Load, CPU, Memoria, etc)

  • metriche prelevate in Pull da un Prometheus Server

  • Alert Manager configurato per inviare alert su alcune soglie (carico alto, richieste lente, server down)

    • alert inviati su canale Slack

Metriche

epas prometheus metrics

Metriche su Grafana

dashboard prometheus epas 1

Metriche su Grafana

dashboard prometheus epas 2

Notifiche metriche con problemi

epas slack notification monitoring

Code base

epas gitlab project

Issues - Branch - Merge Request

epas gitlab issues

Docker registry

epas gitlab docker registry

Continuous Integration

epas jenkins overview

Build dell’immagine docker

epas jenkins docker build

CI si, CD no

epas jenkins production overview

We love docker

  • docker & docker-compose per deploy

    • no more: it works on my machine works on my machine meme

    • configurazione a partire da variabili di ambiente docker

docker-compose.yml

version: '3.1'

   ############################################################################
   #                             ePAS Server                                  #
   # Configurazione per l'avvio di ePAS e di un'eventuale postgres locale     #
   ############################################################################

services:

   ### Le variabili volumes sono mappate come - host_folder:container_folder
   ### Correggere all'occorrenza i path per le cartelle sull'host ma lasciare
   ### inalterati i path sui container docker

  epas:
    image: consiglionazionalericerche/epas
    container_name: epas
    volumes:
      - ./epas/logs:/home/epas/epas/logs
      - ./epas/attachments:/home/epas/epas/data/attachments
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
    #Non è necessario esporre la porta 9000 se si utilizza un proxy per
    #servire le richieste http/https. L'utilizzo del proxy https è fortemente
    #consigliato in produzione, utilizzare per esempio traefik.
    ports:
      - 9000:9000
    #labels:
    #  - traefik.enable=true
    #  - traefik.backend=epas
    #  - traefik.frontend.rule=Host:${HOST_NAME}
    #  - traefik.port=9000
    environment:
      - VIRTUAL_HOST=${HOST_NAME}
      #- PROTOCOL=https                         # default: http  -- (http,https)
      ##- EPAS_SHIB_LOGIN=                      # default: false  -- (true,false)
      - JOBS_ACTIVE=true                        # default: false  -- (true,false) --  Se forzato a true abilita l'esecuzione di tutti i job
      #- SKIP_IP_CHECK=                         # default: false -- (true,false) -- Disabilita il controllo sugli indirizzi ip delle richieste
      - FLOWS_ACTIVE=true
      #- URL_ATTESTATI=                         # default: https://attestativ2.rm.cnr.it
      #- URL_USER=
      #- URL_PASS=
      ######## LOGS ###########
      #- LOG_LEVEL=                            # Opzionale. default: INFO   -- (OFF,FATAL,ERROR,WARN,INFO,DEBUG,TRACE,ALL)
      - APPENDERS=file                         # Opzionale. default: stdout, stderr -- (stdout, stderr, file, graylog2). Abilita i log sulla console, file e server graylog
      #- GRAYLOG_HOST=                         # Obbligatorio se attivato log sull'appender graylog2. default: null
      #- GRAYLOG_PORT=                         # Opzionale. default: 3514
      #- GRAYLOG_ORIGIN_HOST=                  # Opzionale. default: valore in VIRTUAL_HOST
      ###### Container ########
      #- BACKUP_CRON=                          # default: disattivato. (utilizzare il format del crontab. Es. 0 0 * * *)
      #- CERT_NAME=                            # default: valore specificato in VIRTUAL_HOST -- Specifica un nome diverso per i file del certificato SSL
      - TZ=Europe/Rome
      #### Connessione DB ####
      - DB_HOST=${DB_HOST}                     # default: indirizzo assegnato al container postgres linkato
      - DB_NAME=${DB_NAME}                     # default: epas
      - DB_PASS=${DB_PASS}                     # Obbligatoria. Password per accedere al database server
      #- DB_PORT=5432                          # default: 5432
      #- DB_USER=${DB_USER}                    # default: postgres
      #### server SMTP ####
      - SMTP_HOST=${SMTP_HOST}                # default: smtp.cnr.it
      #- SMTP_PORT=${SMTP_PORT}                # default: 25 se SMTP_CHANNEL è impostato clear o starttls; 465 se impostato su ssl
      ##- SMTP_CHANNEL=${SMTP_CHANNEL}          # default: clear -- (clear, ssl ,starttls)
      #- SMTP_FROM=${SMTP_FROM}                # default: epas@cnr.it -- Indirizzo utilizzato per il campo mittente delle mail inviate dal sistema
      #- SMTP_PROTOCOL=${SMTP_PROTOCOL}        # default: smtp -- (smtp, smtps)
      #- SMTP_USER=${SMTP_USER}                # user utilizzato per l'autenticazione sul server smtp (se necessario)
      #- SMTP_PASS=${SMTP_PASS}                # password utilizzato per l'autenticazione sul server smtp (se necessaria)
      #### Autenticazione LDAP ####
      #- LDAP_LOGIN=true                       # default: false. Impostare a true per attivare l'autenticazione tramite LDAP
      #- LDAP_URL=${LDAP_URL}                  # url del server LDAP, per esempio ldap://ldap.cnr.it:389
      #- LDAP_STARTTLS=${LDAP_STARTTLS}        # default: false. Se impostato a true attiva la connessione cifrata tramite il protocollo starttls
      ##- LDAP_TIMEOUT=${LDAP_TIMEOUT}          # default: 1000. Time in millisecondi della connessione LDAP.
      #- LDAP_DN_BASE=${LDAP_DN_BASE}          # DN per la ricerca degli utenti su LDAP, per esempio ou=People,dc=iit,dc=cnr,dc=it
      ##- LDAP_LOGIN_RETURN=${LDAP_LOGIN_RETURN} # default: /. Indirizzo relativo di reindirizzamento dopo il login LDAP.
      ##- LDAP_EPPN_ATTRIBUTE_NAME=${LDAP_EPPN_ATTRIBUTE_NAME}  # default: eduPersonPrincipalName. Campo LDAP utilizzato per il mapping con il campo eppn presente in ePAS.
      ### I due parametri successivi sono da impostare solo nel caso sia necessario effettuare la prima connessione ad LDAP con un utente privilegiato.
      ##- LDAP_BIND_DN=${LDAP_BIND_DN}                                           # Eventuale DN dell'utente LDAP privilegato
      ##- LDAP_BIND_CREDENTIALS=${LDAP_BIND_CREDENTIALS}                         # Eventuale password dell'utente LDAP privilegato
      ##- LDAP_AUTHENTICATE_USER_SEARCH_DN=${LDAP_AUTHENTICATE_USER_SEARCH_DN}   # Da utilizzare solo è presente un LDAP_BIND_DN. L'utente viene cercato su LDAP con
                                                                                 # l'utente amministratore e poi verificata l'autenticazione facendo una search LDAP
                                                                                 # con le credenziali utente con contesto uguale a questo parametro. Es. o=cnr,c=it
      #### Invio Segnalazioni via email
      #- REPORT_TO=${REPORT_TO}                 # default: epas@iit.cnr.it
      #- REPORT_FROM=${REPORT_FROM}             # default: segnalazioni@epas.tools.iit.cnr.it
      #- REPORT_SUBJECT=${REPORT_SUBJECT}       # default: Segnalazione ePAS

      #- TELEWORK_ACTIVE=${TELEWORK_ACTIVE}   # default: false
      #- TELEWORK_BASEURL=${TELEWORK_BASEURL}   # default: http://telework-stampings:8080
      #- TELEWORK_USER=${TELEWORK_USER}   # default: app.epas
      #- TELEWORK_PASS=${TELEWORK_PASS}   # default: chiedere al team di sviluppo

    restart: unless-stopped

  postgres:
    image: postgres:12
    environment:
      - POSTGRES_PASSWORD=${DB_PASS}
    volumes:
      - ./postgres/data:/var/lib/postgresql/data
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro

    restart: unless-stopped

Orchestrazione container

containers dont solve all problems

K8S skills need

running k8s in production meme

ePAS opensource

epas github

Licenza di ePAS

  • GNU Affero General Public License v3.0

gnu affero 3 license conditions

ePAS nel catalogo del riuso delle PA

catalogo riuso epas

ePAS nel catalogo del riuso delle PA

catalogo riuso epas funzionalita

ePAS nel catalogo del riuso delle PA

catalogo riuso epas dettaglio

Nuova documentazione ePAS

ePAS per tutto?

  • non può contenere tutte le informazioni del personale

    • non è un sistema di rendicontazione dei progetti

    • non è un sistema di rilevamento delle persone presenti in sede

  • deve assicurare l’interoperabilità e la cooperazione applicativa con altri sistemi

    • servizi REST sono la modalità per interfacciarsi con ePAS

Documentazione servizi REST

documentazione epas github.io rest

REST: permessi

documentazione epas rest assenze
documentazione epas rest assenze periodo
documentazione epas rest assenze inserimento

REST: cartellino giorno/mese per ufficio

documentazione epas cartellino by office

ePAS client Opensource

ePAS client GitHub

epas client github

ePAS client GitHub - Introduzione

epas client github introduzione

ePAS client GitHub - Requisiti

epas client github parametri

ePAS client GitHub - Parametri

epas client github parametri 1

ePAS client GitHub - Parametri

epas client github parametri 2

ePAS client GitHub - Parametri

epas client github parametri 3

ePAS client GitHub - Parametri

epas client github parametri 4

ePAS client GitHub - Parametri

epas client github parametri 5

ePAS client GitHub - Troubleshooting

epas client github troubleshooting

ePAS client SQL GitHub

epas client sql github

Grazie per l’attenzione

epas workshop ictalk@cnr 2021