Systemd pare forse troppo veloce ad avviare i server su cui lavoro, dei DELL PowerEdge T110-II con dischi SATA in mirror.
Me ne sono accorto perché, all’avvio del server, il database postgresql non veniva avviato ed il relativo servizio di systemd era in stato «failed». Nei log di postgresql non c’erano errori, ma il database era spento.
Avviare postgresql via systemd da linea di comando ha sempre funzionato correttamente, ma ovviamente questo avviene solo dopo aver avviato il sistema, quando la macchina è meno carica. Difatti all’avvio, systemd fa partire in parallelo tutti i servizi che non hanno dipendenze tra loro. Tutti questi, partendo, leggono dal disco, il file system risponde quindi più lentamente del normale, e postgresql va in timeout.
Archivi categoria: Debian
Creare un nuova directory in LDAP con la nuova configurazione in /etc/ldap/slapd.d
Quando si installa il pacchetto slapd, si configura una directory, generalmente chiamata dc=nodomain. Da quel punto in poi, tutta la modifica alla configurazione può essere fatta con un client LDAP, oppure si può operare direttamente con i file. Vediamo questa seconda via.
La prima cosa da considerare è che una directory LDAP viene memorizzata in una directory del file system tramite vari file che contengono dati e indici. Il sistema più vecchio di memorizzazione è quello chiamato bdb (Oracle Berkeley DB), ma ne esistono anche altri quali hdb (hierarchical Berkeley DB), mdb (Memory-Mapped DB) e sql. Ce ne sono anche altri, ma non sono generici. Scartiamo l’ultimo della lista, sql, poiché si tratta di uno strumento che permette solo di leggere dati, senza poterli modificare. Scartiamo anche il primo e il secondo, bdb e hdb, che sono ormai vetusti e addirittura sconsigliati per l’uso. Ci rimane sostanzialmente mdb. Continua a leggere
Operare manualmente sulla mappatura UID/SID di winbind nel formato tdb2
Per collegare una macchina unix o Linux ad una Windows per l’autenticazione, si può utilizzare il winbind, cioè quella parte di samba che permette di autenticare gli utenti tramite le loro credenziali di dominio. Una volta che l’utente è autenticato, viene creato una utenza corrispettiva a quella Windows anche su Unix. La nuova utenza avrà un proprio UID e un GID generati al volo da winbind, ma quando l’utente tornerà una seconda volta a fare l’accesso a Unix, sarà meglio che trovi gli stessi UID e GID, così da avere gli stessi diritti che aveva al primo accesso. Per far sì che UID e GID siano mantenuti, questi vengono memorizzati da qualche parte e associati al SID (cioè all’UID per Windows).
Nel caso che si debbano avere più macchine unix collegate allo stesso dominio Windows, è il caso di memorizzare queste informazioni in un luogo accessibile a tutte le macchine, come ad esempio il dominio Windows stesso (utilizzando l’estensione SFU), oppure in un LDAP, oppure in alcuni file che possono essere periodicamente copiati dalla macchina unix principale alle secondarie. Invece, se la macchina unix è una sola, allora si possono semplicemente utilizzare dei file sul server unix stesso.
Per dire a winbind quale percorso seguire, vanno impostati i «backend» della mappatura degli identificatori, detta idmap. Nel mio caso ho utilizzato il backend tdb2, cioè la nuova versione del tdb («Trivial DataBase», che in italiano significa «base dati elementare»). Nel file di configurazione di samba, ho scritto:
idmap config *:backend = tdb2 idmap config *:range = 4000-4100
Che vuol dire: per le utenze di qualsiasi dominio Windows, memorizza le associazioni SID/UID e SID/GID tramite il backend tdb2. Inoltre crea gli UID e GID nell’intervallo da 4000 a 4100, in modo da essere sicuro che non si sovrappongano a UID e GID già presenti sul sistema unix locale. (Nota: l’intervallo per UID e GID locali è definito in /etc/login.defs
.)
Per tutti quelli che usano Debian GNU/Linux (state già usando tutti Debian, vero?), tdb2 andrà a creare il suo database nella directory /var/lib/samba
e lo chiamerà idmap2.tdb
.
Questo database è — appunto — elementare: cioè è capace di inserire solo dati nella forma chiave/valore. Per vedere quali chiavi sono memorizzate, si può usare il comando tdbtool in questo modo:
root@miura:~# tdbtool /var/lib/samba/idmap2.tdb keys key 9 bytes: GID 4037 key 43 bytes: S-1-5-21-1142429371-1648316-403635728-1131 key 9 bytes: GID 4024 key 9 bytes: UID 4043 key 43 bytes: S-1-5-21-1142429371-1648316-403635728-1136 [...]
come si vede, le chiavi sono a volte un UID a volte un GID, a volte un SID. Non è scritto nella documentazione online, ma l’informazione su quanto sia lunga la chiave è di grande aiuto: la chiave “UID 4043” è lunga 9 byte, ma sono solo 8 caratteri, quindi c’è qualcos’altro. Idem per le altre chiavi.
Per sapere a cosa è associata una certa chiave potremmo usare lo stesso comando, con argomenti diversi. Proviamo:
root@miura:~# tdbtool /var/lib/samba/idmap2.tdb show 'GID 4037' fetch failed
L’errore è criptico, ma ricordando il messaggio precedente sulla lunghezza della chiave, e con un po’ di fantasia (o leggendo il codice sorgente), si può trovare il comando corretto, con l’aggiunta di un byte 0 alla fine della chiave:
root@miura:~# tdbtool /var/lib/samba/idmap2.tdb show 'GID 4037\0' key 9 bytes GID 4037 data 43 bytes [000] 53 2D 31 2D 35 2D 32 31 2D 31 31 34 32 34 32 39 S-1-5-21 -1142429 [010] 33 37 31 2D 31 36 34 38 33 31 36 2D 34 30 33 36 371-1648 316-4036 [020] 33 35 37 32 38 2D 31 31 38 35 00 35728-11 85
bene, adesso non ci sono errori: alla chiave GID 4043 è associato il SID S-1-5-21-1142429371-1648316-403635728-1185, e viceversa:
root@miura:~# tdbtool /var/lib/samba/idmap2.tdb show \ 'S-1-5-21-1142429371-1648316-403635728-1185\0' key 43 bytes S-1-5-21-1142429371-1648316-403635728-1185 data 9 bytes [000] 47 49 44 20 34 30 33 37 00 GID 4037
Lo stesso comando permette anche di cancellare un’associazione, ma questa operazione — ora che abbiamo capito che winbind scrive due record per ogni associazione — va fatta per entrambe le chiavi. Il comando in questo caso non fornisce nessun messaggio riguardo l’esito, nel miglior stile unix:
root@miura:~# tdbtool /var/lib/samba/idmap2.tdb delete \ 'S-1-5-21-1142429371-1648316-403635728-1185\0' root@miura:~# tdbtool /var/lib/samba/idmap2.tdb delete 'GID 4037\0'
Chiudo così questo breve excursus sul trivial database, che nel mio caso è il frutto dello studio dovuto ad un problema, su un server, che presentava due utenti con lo stesso UID. Erano difatti due diverse associazioni memorizzate nel tdb di winbind: una era riferita ad una utenza effettivamente presente sul dominio, mentre l’altra era una associazione rimasta memorizzata nonostante l’utenza sul dominio fosse stata cancellata. Ah, già, dimenticavo: winbind non cancella mai le associazioni locali SID/UID.
Come accedere a più macchine in DMZ tramite un solo indirizzo IP e un forward proxy
In ufficio abbiamo un domino Internet locale e varie macchine con alcune applicazioni web che operano in maniera federata, vale a dire che quando ci si collega alla prima si viene rimandati ad un’altra per l’autenticazione e comincia un rimpallo tra le varie macchine (sempre tramite http redirect, cioè tramite il browser sul PC client) finché non si supera sia l’autenticazione che l’autorizzazione. Questa modalità di autenticazione è chiamata federativa o anche «per attestazioni», poiché in una applicazione ci si fida di un server di autenticazione, il quale può essere federato con altri tra i quali è stabilita la fiducia. L’idea è che si arrivi ad autenticare l’utente in maniera automatica, tramite il single sign on, vale a dire che l’utente viene riconosciuto perché ha già fatto il login nel suo sistema operativo e non deve rifarlo per ogni applicazione. Il protocollo utilizzato per scambiare informazioni tra i vari siti implicati è quello SAML, mentre, per fare un po’ di nomi, le tecnologie coinvolte sono la fedlet di Java, la AD FS di Microsoft e altre meno conosciute.
Facciamo l’esempio dell’ufficio con tutte le macchine nel dominio ufficio.local. Avremo quindi dei nomi di macchine fisiche come vm1.ufficio.local o vm2.ufficio.local, e CNAME per le applicazioni, come adfs.ufficio.local e app1.ufficio.local. Le applicazioni sono tutte web, ma utilizzano le porte più disparate, la 443, 8443, la 9653 ed altre ancora, tutte rigorosamente cifrate tramite SSL con certificati emessi dalla ca.ufficio.local.
Il problema è: voglio permettere l’accesso da fuori dell’ufficio protetto dal firewall, senza utilizzare nessuna VPN che dia accesso a tutta la rete interna o che richieda di configurare il firewall in maniera potenzialmente errata.
La soluzione è stata la seguente:
-
configurare il primo firewall per inoltrare tutte le porte delle varie applicazioni web al secondo firewall,
-
configurare il secondo firewall in modo che inoltri tutte le porte delle varie applicazioni ad una sola porta di una macchina proxy sulla quale è configurato pound,
-
configurare pound perché inoltri le varie richieste alla macchina corretta nella LAN.
pound è un proxy HTTP, vale a dire che si mette in ascolto su una porta e, tramite protocollo HTTP, riceve le richieste che poi smista in base a regole sulle intestazioni della richiesta HTTP. pound è in grado di mettersi in ascolto su una porta SSL e di comunicare con il server effettivo, sempre via SSL.
Perché il certificato SSL di pound sia riconosciuto e accettato dai browser per tutti i nomi delle varie macchine, ci sono alcune strade:
-
la prima è avere un certificato per ogni macchina (in questo caso pound usa l’estensione SNI (sigla che sta per Server Name Indication: suggerimento sul nome del server) del protocollo TLS (l’attuale estensione di SSL) per capire quale servername è richiesto dal client),
-
la seconda è avere un certificato che corrisponde a tanti nomi (in questo caso di utilizza l’estensione subjectAlternativeNames del certificato),
-
la terza è avere un certificato che vale per tutto il dominio.
Utilizzo la seconda possibilità e genero un certificato e una richiesta di firma (CSR: Certificate Sign Request) usando lo strumento keytool di java. Nota: questo strumento non crea automaticamente la CSR con tutti i subjectAlternativeNames, ma li si deve specificare sia per la creazione delle chiavi iniziali, sia per la creazione della CSR.
Userò pound.ufficio.local che è il nome della macchina sulla quale ho messo pound, xi12.ufficio.local che è una delle applicazioni, erpln.ufficio.local è la seconda applicazione, adfs.ufficio.local è la terza.
keytool -genkeypair -alias pound -keyalg RSA -keysize 2048 \ -dname "CN=pound.ufficio.local, OU=demo, O=ufficio, L=Torino, C=IT" \ -ext SAN=dns:pound.ufficio.local,dns:xi12.ufficio.local,\ dns:erpln.ufficio.local,dns:adfs.ufficio.local \ -validity 3650 -keypass 'password' -keystore pound.pfx \ -storepass 'password' -storetype PKCS12 keytool -certreq -alias pound -file pound.csr \ -ext SAN=dns:pound.ufficio.local,dns:xi12.ufficio.local,\ dns:erpln.ufficio.local,dns:adfs.ufficio.local \ -keypass 'password' -keystore pound.pfx -storepass 'password' \ -storetype PKCS12
A questo punto prendo il file pound.csr, lo porto alla mia autorità di certificazione, la quale restituisce il certificato pound.cer.
Poiché pound vuole un solo file con la chiave privata e con il certificato, tutto in formato PEM, estraggo la chiave privata da file PFX iniziale e le tolgo la password di protezione, poi creo il file completo per pound:
openssl pkcs12 -in pound.pfx -nocerts -out pound.pw.key # sempre con password openssl rsa -in pound.pw.key -out pound.nopw.key # senza password cat pound.cer pound.nopw.key > ssl.pem rm pound.pfx pound.csr pound.cer pound.nopw.key pound.pw.key sudo mv ssl.pem /etc/pound/ssl.pem sudo chown root:root /etc/pound/ssl.pem sudo chmod go-rwx /etc/pound/ssl.pem
Infine creo il file di configurazione per pound, /etc/pound/pound.cfg:
ListenHTTPS Address 192.168.245.99 Port 8442 Cert "/etc/pound/ssl.pem" LogLevel 5 ## allow PUT and DELETE also (by default only GET, POST and HEAD)?: xHTTP 1 Service IgnoreCase 1 URL ".*" HeadRequire "Host:.*xi12.ufficio.local:9543.*" BackEnd Address xi12.ufficio.local Port 9543 HTTPS End End Service IgnoreCase 1 URL "^/(bundles/|Scripts/|infor|api/|template/|Content/|CollaborationUI/|webresource/|user/|IONAPIUI/).*" HeadRequire "Host:.*xi12.ufficio.local.*" BackEnd Address xi12.ufficio.local Port 8443 HTTPS End End Service IgnoreCase 1 URL "^/lnui/.*" HeadRequire "Host:.*erpln.ufficio.local.*" BackEnd Address erpln.ufficio.local Port 8443 HTTPS End End Service IgnoreCase 1 URL "^/adfs.*" HeadRequire "Host:.*adfs.ufficio.local.*" BackEnd Address adfs.ufficio.local Port 443 HTTPS End End End
Ora si può avviare pound.
Come punto finale, per potersi collegare dall’esterno, si deve inserire nel proprio file /etc/hosts una riga con l’ip pubblico dell’ufficio (quello associato al firewall esterno) e tutti i nomi delle macchine e applicazioni alle quali si deve accedere.
Una volta fatta la prova, si vede che questa configurazione non funziona. Il problema che ho riscontrato è che il server adfs.ufficio.local utilizza a sua volta la SNI, ma pound non imposta l’estensione servername di openssl e quindi la SNI non funziona. A questo punto ho cercato la soluzione sul web e ho trovato che il problema è già stato sollevato da un’altra persona, alla quale è stata fornita una patch non ancora inserita nel codice di pound. La patch però funziona: difatti l’ho scaricata, poi ho fatto le modifiche suggerite nella pagina in questione, ho ricompilato il pacchetto Debian e l’ho installato e provato. Funziona. La patch è in questo thread.
logrotate e postrotate
Il logrotate è un strumento molto utile che gestisce i file di log delle varie applicazioni. Ogni giorno viene eseguito dal cron e, in base alla configurazione, archivia tutti i log. Tra le cose interessanti c’è la possibilità di eseguire un comando dopo l’archiviazione del log (e prima della sua eventuale compressione). L’operazione che viene eseguita normalmente a fine archiviazione, è quella di avvisare l’applicazione di utilizzare un nuovo file di log.
Ad esempio, nel file /etc/logrotate.d/rsyslog di Debian c’è scritto:
postrotate invoke-rc.d rsyslog rotate > /dev/null endscript
oppure, nel file /etc/logrotate.d/apache2 c’è scritto:
postrotate if /etc/init.d/apache2 status > /dev/null ; then \ /etc/init.d/apache2 reload > /dev/null; \ fi; endscript
Il manuale, a proposito del postrotate, dice:
The lines between postrotate and endscript (both of which must appear on lines by themselves) are executed (using /bin/sh) after the log file is rotated. These directives may only appear inside a log file definition. Normally, the absolute path to the log file is passed as first argument to the script. If sharedscripts is specified, whole pattern is passed to the script. See also prerotate. See sharedscripts and nosharedscripts for error handling.
Il secondo esempio dovrebbe fare scattare un campanello d’allarme riguardo la sintassi da usare nel postrotate: non si tratta di uno script composto da vari comandi, ma di linee che vengono eseguite tramite la shell. Allora, se il comando è uno solo, come nel caso di rsyslog, non c’è problema, ma se si usano varie linee, è necessario concatenarle tramite il backslash a fine riga, e utilizzare sempre il separatore «;» tra i comandi.