2015-04-13 19 views
5

Sto usando jTDS per connettermi a SQLServer. JTDS internamente utilizza GSS per ottenere un ticket di servizio di kerberos e stabilire un contesto sicuro. Poiché la mia app è longeva e le mie connessioni sono mantenute in vita per tutto il tempo ho bisogno che il ticket di servizio di kerberos sia rinnovabile per consentire al server SQL di rinnovarle da solo (le politiche kdc sono impostate per scadere tutti i ticket dopo 12 ore).Come ottenere i biglietti di kerberos rinnovabili usando java GSS + JAAS

Cosa jTDS fa per ottenere un token Kerberos è (più o meno) i seguenti:

GSSManager manager = GSSManager.getInstance(); 

// Oids for Kerberos5 
Oid mech = new Oid("1.2.840.113554.1.2.2"); 
Oid nameType = new Oid("1.2.840.113554.1.2.2.1"); 

// Canonicalize hostname to create SPN like MIT Kerberos does 
GSSName serverName = manager.createName("MSSQLSvc/" + host + ":" + port, nameType); 

GSSContext gssContext = manager.createContext(serverName, mech, null, GSSContext.DEFAULT_LIFETIME); 
gssContext.requestMutualAuth(false); 
gssContext.requestCredDeleg(true); 

byte[] ticket = gssContext.initSecContext(new byte[0], 0, 0); 

Quello che ho il sospetto è che il biglietto io sto ottenendo non è rinnovabile. Sto controllando che facendo qualcosa di simile a quanto segue:

ExtendedGSSContext extendedContext = (ExtendedGSSContext) gssContext; 
boolean[] flags = (boolean[]) extendedContext.inquireSecContext(InquireType.KRB5_GET_TKT_FLAGS); 
System.out.println("Renewable = " + flags[8]); 

Nella nostra particolare configurazione GSS sta ottenendo Kerberos TGT dal modulo di login JAAS. Abbiamo la seguente variabile impostata su false -Djavax.security.auth.useSubjectCredsOnly=false e nel file login.cfg abbiamo la seguente modulo di login configurato:

com.sun.security.jgss.krb5.initiate { 
    com.sun.security.auth.module.Krb5LoginModule required 
     useKeytTab=true 
     keyTab="/home/batman/.batman.ktab" 
     principal="[email protected]" 
     storeKey=true 
     doNotPrompt=true 
     debug=false 
}; 

Un'altra cosa che ho notato è che il metodo di GSSContextgetLifetime() non sembra funzionare. Restituisce sempre 2147483647 (max int) indipendentemente dalla durata effettiva del ticket.

Mi sento a mio agio con il driver jTDS ramificato, così posso modificare il modo in cui stabilisce un contesto GSS se necessario.

Quello che ho cercato:

usare l'esecuzione nativa di GSS api:

Questo funziona bene per me in termini di ottenimento di biglietti rinnovabili ma imposesses un'altra serie di questioni (in termini di garanzia che la cache del ticket sia impostata correttamente e che i ticket siano correttamente rinnovati). Se riesco a bypassare questa opzione sarebbe bello. Una cosa che osservo qui è che il metodo getLifetime() restituisce effettivamente la durata effettiva in secondi del ticket.

reimplementare KerberosLoginModule:

Sulla base della risposta a questa domanda ho Jaas - Requesting Renewable Kerberos Tickets reimplementato LoginModule per impostare la RENEW KDCOption in KrbAsReqBuilder prima di richiedere un TGT. Ciò funziona bene nel senso che ottengo un TGT rinnovabile, ma il ticket ottenuto da quel TGT da GSS non è ancora rinnovabile. Se imposto un breakpoint nel costruttore dell'oggetto KDCOption e imposta manualmente il flag RENEW su ogni richiesta (anche il KrbTgsReq eseguito da GSS) funziona, ma rendere produttiva tale modifica richiede una riscrittura maggiore su GSS che non mi sento a mio agio con .

risposta

1

Per gli amministratori, il fatto che i ticket Kerberos abbiano una durata è una funzione di sicurezza importante. L'utente conosce una password, quindi può ottenere un nuovo biglietto in qualsiasi momento. Ma per l'intruso è un problema - dopo che il ticket è scaduto, non può essere utilizzato per entrare nel sistema. Gli amministratori vogliono che questa durata sia il più breve possibile, ma non troppo breve (come 1 ora) perché gli utenti genererebbero 10x di richieste di login in più di adesso e sarebbe difficile da gestire per ActiveDirectory.

Quando è necessario autenticarsi con Kerberos, è necessario utilizzare il pool di connessioni (e DataSource). Per utilizzare questa funzione in jTDS è necessario aggiungere ConnectionPoolImplementation (consigliato: DBCP o c3p0, vedere: http://jtds.sourceforge.net/features.html).

Se desideri scrivere l'applicazione utilizzando il vecchio modo di connettersi al database (senza origine dati, ovvero creare una connessione e mantenerla in vita perché è costosa da creare ..) il prossimo ostacolo sarebbe "rinnova la durata" . In ActiveDirectory i ticket Kerberos possono essere rinnovati automaticamente entro 7 giorni. C'è un'impostazione globale in AD che consente di impostare lì 0 (una durata di rinnovo indefinita), ma è necessario convincere l'amministratore di dominio a ridurre la sicurezza dell'intero dominio solo perché un servizio non funzionerebbe senza di esso.

+0

Grazie! Usiamo un pool di connessioni e lo impostiamo per scadere le nostre connessioni dopo 6 ore, quindi non stiamo raggiungendo la scadenza. Sono d'accordo che è una buona pratica e un buon workaround il mio problema, ma in alcuni casi non posso andare per quella soluzione. Capisco che i biglietti possono essere rinnovati fino a 7 giorni (la nostra configurazione è quella predefinita in tal senso) ma va bene per noi. Il problema è che i token che ottengo non sono rinnovabili (hanno la flag di rinnovo impostata su false) quindi dopo 12 ore sono inutili. – Claudio

+0

Ho assegnato questa risposta con la taglia (che stava per scadere). Non risolve il mio problema ma forse è utile per qualcun altro. – Claudio