Grouper

Da sia.
Versione del 3 mar 2025 alle 16:29 di Malvezzi (discussione | contributi) (→‎grouper-2.5)
(diff) ← Versione meno recente | Versione attuale (diff) | Versione più recente → (diff)
Vai alla navigazione Vai alla ricerca

Introduzione

Grouper e' un promettentissimo progetto di Internet2 per la gestione e la delega della gestione dei gruppi. Grouper e' veramente completo: legge la base dati utenti da ldap o da un db relazionale, crea i gruppi (da linea di comando, tramite web service o con interfaccia web) e poi li immette (provision) in ldap.

Cosa funziona gia'

  • creare i gruppi da ui e da shell;
  • il client web service funziona in una caso banale;
  • ho chiesto alla ml per avere due tipi di gruppi con provisioning diverso;
  • provision con schema posixGroup (vedi gli hooks per creare il gidnumber) -- rifatto dopo la migrazione ad oracle grazie all'aiuto di Chris Hyzer

Cosa manca da capire

Funzionamento dei privilegi di delega.

Cosa manca da fare

  • passare a oracle (fatto);
  • shibbolettizzare grouper;
  • aggiungere anche le objectClass samba;
  • modificare le acl di ldap per
    • permettere a grouper di inserire i gruppi con privilegi minori di admin (fatto salvo l'aggiunta dello ou)
    • nascondere i gruppi
  • importare i gruppi presenti su domain e ahab;
  • modificare il delta per non sovrascrivere gli attributi utenti impostati da grouper (variante: modificare il raccoglitore per prendere questi dati da grouper);
  • creare gli script di "inventario" per ricreare eventualmente i gruppi;
  • inizializzare i privilegi

Cosa ho fatto

Le istruzioni che ho seguito sono:

Il diagramma grouper ed ldap illustra quali sono i componenti di grouper e come si relazionano con ldap e eventuali db relazionali.

Grouper mantiene i gruppi in un db locale che adesso e' oracle su oracle10g.dmz-int.unimo.it.

Ogni componente di grouper (le api, il tool di provisioning, la ui, il web service) e' in un pacchetto diverso: l'unico fondamentale sono le api.

Per usare gsh è meglio installare rlwrap poi:

sudo apt-get install rlwrap 
rlwrap gsh.sh

Come connettere ldap con grouper

Le api dialogano in lettura con lo ldap tramite le impostazioni in grouper.api/conf/sources.xml.

Lo stesso sources.xml viene incluso nelle ui. Se si cambia sources.xml, ricordarsi di lanciare

cd /opt/grouper.ui
ant war

per la ui e spostare il war risultante nella cartella webapps di tomcat.

Come connettere grouper con ldap

Il provisioning (cioe' la scrittura dei gruppi in ldap) la fa il componente ldapcng. ldappcng deve essere scompattato sopra grouper.api (i file di configurazione di ldappng devono finire nella cartella conf delle api, i jar nella cartella lib/custom).

I file di rilievo sono:

  • ldappc-internal.xml: bootstrap di velocity, probabilmente per le sostituzioni;
  • ldappc.properties: file di definizioni per vt-ldap per il provisioning verso i server ldap; serve al file ldappcng.xml;
  • ldappc-service.xml: definisce il servizo ldappcng (in cui inietta il file di proprietà ldappc.properties) e definisce il grouper.AttributeResolver (sempre con il file di proprietà);
  • ldappcng.xml: i template dei gruppi, sembra un file php, in cui fare le sostituzioni dei valori che provengono dal file successivo; genera lo SPML;
  • ldappc-resolver.xml: il resolver dei valori citati nel file precedente. Si tratta della stessa sintassi (e dello stesso programma) dell'attribute resolver di shibboleth;
  • ldappc-ldap.xml: il file di configurazione per vt-ldap.

ldappc-resolver.xml

In questo file ho modificato la definizione del cn per i cn composti. Infatti i cn di grouper sono del tipo: cn=unimore:sia:test e con il default:

 <resolver:AttributeDefinition id="cn" xsi:type="ad:Simple" sourceAttributeID="extension">
   <resolver:Dependency ref="GroupDataConnector" />
 </resolver:AttributeDefinition>

vengono tradotti in ldap con dei valori multipli come:

cn=unimore
cn=unimore:sia
cn=unimore:sia:test

Questi valori multipli confondono openldap quando c'e' da genera il dn.

La definizione corretta di cn e':

<resolver:AttributeDefinition id="cn" xsi:type="ad:Simple" >
   <resolver:Dependency ref="cn-extension" />
   <resolver:Dependency ref="cn-name" />
 </resolver:AttributeDefinition>
 <resolver:AttributeDefinition id="cn-extension" xsi:type="ad:Simple" sourceAttributeID="extension">
   <resolver:Dependency ref="GroupDataConnector" />
 </resolver:AttributeDefinition>
 <resolver:AttributeDefinition id="cn-name" xsi:type="ad:Simple" sourceAttributeID="name">
   <resolver:Dependency ref="GroupDataConnector" />
 </resolver:AttributeDefinition>

In questo modo la definizione del dn e del cn sono allineati su sourceAttributeID="name". In piu' nella entry del gruppo il cn compare a valori multipli.

Se un valore e' sufficiente, allora basta cambiare:

<resolver:AttributeDefinition id="cn" xsi:type="ad:Simple" sourceAttributeID="name">
   <resolver:Dependency ref="GroupDataConnector" />
 </resolver:AttributeDefinition>

Per avere la lista dei membri dei gruppi, accertarsi che il source per members-jdbc punti a una datasource corretta. Per un motivo che non mi e' chiaro solo il server ldap funziona (avrei immaginato che il default, jdbc, cioe' il database di grouper andasse bene).

 <resolver:AttributeDefinition id="members-jdbc" xsi:type="grouper:Member" sourceAttributeID="members">
   <resolver:Dependency ref="GroupDataConnector" />
   <grouper:Attribute id="id" source="unimore" />
 </resolver:AttributeDefinition>

Per avere un provisioning diverso per due tipi di gruppi (ad esempio groupOfNames e PosixGroup), bisogna definire due groupMapping in ldappc-resolver.xml, con un filtro tipo:

  <resolver:DataConnector id="GroupDataConnector" xsi:type="grouper:GroupDataConnector">
  <grouper:GroupFilter xsi:type="grouper:OR">
   <grouper:GroupFilter xsi:type="grouper:StemName" name="unimore:plains" scope="SUB" />
   <grouper:GroupFilter xsi:type="grouper:StemName" name="etc" scope="SUB" />
  </grouper:GroupFilter>
   <grouper:Attribute id="members" />
   <grouper:Attribute id="groups" />
 </resolver:DataConnector>

e

<resolver:DataConnector id="SambaGroupDataConnector" xsi:type="grouper:GroupDataConnector">
   <grouper:GroupFilter xsi:type="grouper:StemName" name="unimore:domains" scope="SUB" />
   <grouper:Attribute id="members" />
   <grouper:Attribute id="groups" />
 </resolver:DataConnector>

Dopo bisogna ricordarsi di includere entrambi i DataConnector in tutte le definizioni di attributi, tipo:

 <resolver:AttributeDefinition id="description" xsi:type="ad:Simple">
   <resolver:Dependency ref="GroupDataConnector" />
   <resolver:Dependency ref="SambaGroupDataConnector" />
 </resolver:AttributeDefinition>

Bisogna duplicare la definizione dell'objectClass e del dn. Nell'objectClass bisogna aver cura di introdurre almeno un objectClass per ogni tipo gruppo che non sia presente nell'altro gruppo. Questa objectClass permette a grouper di capire la differenza tra i gruppi tramite la chiave 'identifiyngAttribute' in ldappcng.xml.

Da notare:

 <resolver:AttributeDefinition id="hasMember" xsi:type="grouper:Member" sourceAttributeID="members">
   <resolver:Dependency ref="GroupDataConnector" />
   <resolver:Dependency ref="SambaGroupDataConnector" />
   <grouper:Attribute id="name" source="unimore" />
 </resolver:AttributeDefinition>
 <resolver:AttributeDefinition id="members-jdbc" xsi:type="grouper:Member" sourceAttributeID="members">
   <resolver:Dependency ref="GroupDataConnector" />
   <resolver:Dependency ref="SambaGroupDataConnector" />
   <grouper:Attribute id="id" source="unimore" />
 </resolver:AttributeDefinition>

Nella prima definizione 'name' coincide con il cn dei membri, per creare delle entry tipo:

hasMember: tizio
hasMember: caio

Nel secondo 'id' e' il dn per delle entry tipo:

member: uid=tizio,ou=people,dc=unimore,dc=it
member: uid=caio,ou=people,dc=unimore,dc=it

Nel file ldappcng.xml bisogna creare una definizione per ciascun gruppo, ad esempio:

    <object id="group" authoritative="true">
     <identifier ref="group-dn" baseId="${groupsOU}">
       <identifyingAttribute name="objectClass" value="groupOfNames" />
     </identifier>
     <attribute name="objectClass" ref="group-objectclass-eduMember" />
     <attribute name="cn" />
     <attribute name="description" />
     <attribute name="hasMember" ref="hasMember" />
     <attribute name="isMemberOf" ref="groupIsMemberOf" />
     <references name="member" emptyValue="" >
       <reference ref="members-jdbc" toObject="member" />
       <reference ref="members-g:gsa" toObject="group" />
     </references>
   </object>
  <object id="samba-group" authoritative="true">
     <identifier ref="group-samba-dn" baseId="${groupsOU}">
       <identifyingAttribute name="objectClass" value="unimoreGroup" />
     </identifier>
     <attribute name="objectClass" ref="group-objectclass-unimoreGroup" />
     <attribute name="cn" />
     <attribute name="description" />
     <attribute name="gidNumber" />
     <attribute name="sambaGroupType" />
     <attribute name="sambaSID" />
     <attribute name="isMemberOf" ref="groupIsMemberOf" />
     <attribute name="memberUid" ref="hasMember" />
     <attribute name="hasMember" ref="hasMember" />
     <references name="member" emptyValue="" >
       <reference ref="members-jdbc" toObject="member" />
       <reference ref="members-g:gsa" toObject="group" />
     </references>
   </object>

Gli attributi gidNumber, sambaGroupType e sambaSID sono definiti nel ldappc-resolver.xml come:

<resolver:AttributeDefinition id="gidNumber" xsi:type="ad:Simple">
   <resolver:Dependency ref="SambaGroupDataConnector" />
 </resolver:AttributeDefinition>


Sincronizzare un gruppo:

bin/gsh.sh -ldappcng -sync etc:sysadmingroup

sincronizzare un utente:

bin/gsh.sh -ldappcng -sync malvezzi

Attributi virtuali

Servono per visualizzare nella ui i subjects in modo diverso che con i semplici campi id (uid) name (cn) o description (description), ma ad esempio con "${subject.cn} ${subject.description}".

Modificare lo sources.xml nella sezione della sorgente dati di interesse (unimore -- nel nostro caso) e aggiungere:

 <init-param>
     <param-name>subjectVirtualAttribute_1_displayName0</param-name>
     <param-value>${subject.name}, ${subject.description}</param-value>
 </init-param>

Questo attributo si può testare in gsh con subject.getAttributeValue("displayName0")

Poi bisogna editare il file /opt/grouper.ui/conf/resources/grouper/media.properties nelle due sezioni (molti distanti tra loro) oppure il file /opt/grouper.ui/conf/grouper-ui.properties nella versione 2.2.1:

subject.display.default=displayName0
[...]
#grouperUi.subjectImg.sourceId.0 = pennperson
#grouperUi.subjectImg.image.0 = user.png
## screen EL has "subject" as an object
#grouperUi.subjectImg.screenEl.0 = ${subject.description}
grouperUi.subjectImg.sourceId.0 = unimore
grouperUi.subjectImg.image.0 = user.png
# screen EL has "subject" as an object
grouperUi.subjectImg.screenEl.0 = ${subject.getAttributeValue("displayName0")}

La prima server per la ui, la seconda per la lite-ui.

Ho anche provato con una modifica nelle dinamic tiles (sempre in media.properties):

unimore.subject.view=/WEB-INF/jsp/custom/unimoreSubjectView.jsp

con il seguente file /opt/grouper.ui/webapp/WEB-INF/jsp/custom/unimoreSubjectView.jsp:

<%@include file="/WEB-INF/jsp/include.jsp"%>
<tiles:importAttribute ignore="true"/><c:set var="attrKey" value="*subject.display.${viewObject.source.id}"/><c:if test="${empty mediaMap[attrKey]}"><c:set var="attrKey"  value="subject.display.default"/></c:if>
<c:if test="${viewObject.isGroup}"><img <grouper:tooltip key="group.icon.tooltip"/> 
   src="grouper/images/group.gif" class="groupIcon" alt="Group" 
   /></c:if><c:if test="${empty inLink}"><span class="<c:out value="${viewObject.subjectType}"/>Subject"></c:if><c:out value="${viewObject['cn']}" />[<c:out   value="${viewObject['description']" /> ] <c:if test="${empty inLink}"></c:if>

ma sembra che venga ignorato.

Shibboleth

Per disabilitare l'autenticazione gestita da tomcat per grouper, modificare il file: /opt/grouper.ui/web-xml-merge-tags.xml commentare le righe:

        <tag name="security-constraint" key="url-pattern"/>
        <tag name="login-config" type="single"/>
        <tag name="security-role" key="role-name"/>

Difficolta'

La difficolte' (risolte) del provisioning sono:

  • problema di accessi (acl) su ldap;
  • conflitti di schema con openldap;
  • aggiunta di attributi calcolati durante la generazione dei gruppi (gidNumber -> vedi usare gli hook)
  • Provisioning diverso per stem diversi: ad esempio lo stem etc:sysadmingroup non deve avere gli attributi posix, mentre lo stem it.unimore si'.

Import/export di dati

Si possono creare gruppi in grouper con:

  • la shell manualmente uno a uno
  • la interfaccia grafica
  • i web service (esiste anche un client java gia' pronto)
  • il servizio import (non l'ho guardato)
  • la shell con il comando -xmlimport.

Upgrade di versione

Istruzioni sul sito di grouper

grouper.api

Ricordarsi gli hook: copiare il build xml ed eseguire ant.

grouper.ui

Modificare il file build.properties.

Copiare dalla versione precedenti il file conf/grouper-ui.properties (contiene il riferimento al logo) ed il file conf/grouperText/grouper.text.en.us.base.properties (nome dell'istituzione, chiave institutionName).

Copiare il logo unimore_logo.png in webapp/grouperExternal/public/assets/images/

Andare in ./dist/grouper/WEB_INF/web.xml ed eliminare tutte le sezioni: security-constraint, login-config, and security-role (altrimenti c'è sempre un errore 403). Meglio ancora fare come scritto nella sezione "Shibboleth".

   ant war

grouper.ws

Modifcare build properties in grouper-ws

#grouper base dir 
grouper.dir=/opt/grouper

poi ricreare il jar:

cd grouper-ws
sudo JAVA_HOME=/usr/lib/jvm/java-6-sun ant

poi modificare il soft link

grouper-2.5

grouper-2.5 è un container docker. Ho seguito il setup manuale maturity level 1 (cioé con il dockerfile).

In /opt/grouperContainer ci sono tre contanier: grouper-daemon, grouper-ui e grouper-ws.

 docker pull i2incommon/grouper:4.12.0
 sudo docker build -t grouper-4.12.0 /opt/grouperContainer
 sudo ./grouperUiDockerRun.sh
 sudo docker exec -it grouper-ui /bin/bash
 sudo docker ps --all
 sudo docker container stop grouper-ui
 sudo docker rm -f grouper-ui
 docker system df
 docker system prune

Si possono copiare file dai container alla VM con:

 sudo docker cp grouper-ui:/log4j.tar

Per i log verificare che l'utente tomcat abbia lo stesso uid nel container e nella VM:

 $ sudo groupadd -r -g 994 tomcat
 $ sudo useradd -r -u 996 -g 994 tomcat

Altre istruzioni soprattutto per i ws: https://wiki.unimore.it/index.php/Setup_grouper25#Web_Services

Aggiornare lo schema del db, vedi punto 32.

Verifica la versione in: Home -> Miscellaneous -> Configure.