Introduzione
Nota: Puoi scaricare la fonte da Github.
Ho lavorato su applicazioni multi-tenant nell’ecosistema .NET per un po ‘di tempo, e una delle sfide più difficili in cui mi sono costantemente incontrato è l’isolamento sicuro degli inquilini, soprattutto quando diversi clienti si aspettano basi, ruoli e funzionalità di gestione separate.
La mia soluzione preferita a questo è stata Keycloakuno strumento di gestione dell’identità e accesso open supply. Con keycloak, mi affido Regni Per isolare le configurazioni degli inquilini, quindi legare tutto bene insieme nella mia applicazione .NET. Ecco come lo faccio.
Perché usare KeyCloak Realms?
Keycloak Realms Lasciare dividere ogni inquilino nel suo “spazio”, completo di utenti, gruppi, ruoli e shopper OAuth/OpenId Join distinti. Dal momento che ogni regno funziona come un silo, posso a bordo di un nuovo cliente (inquilino) solo facendo girare un nuovo regno – non sono richieste importanti modifiche al codice. È molto più semplice che forzare una listing utente gigante a gestire tutti in un unico posto.
Come si adatta a .web
Dal punto di vista principale di ASP.NET, i regni semplificano il flusso di autenticazione della struttura. A ogni regno viene assegnato il proprio Emittente (autorità), ClientIDe facoltativo Segreto del cliente. Tutto quello che devo fare nel mio codice .NET è determinare a quale inquilino appartiene la richiesta, quindi configurare la pipeline di autenticazione per indicare il regno giusto.
Setup KeyCloak: regni e clienti
Immaginiamo di avere due inquilini: inquilino A e inquilino B. In Keycloak:
- Crea regno “Tenanta. ”
- Al suo interno, aggiungi shopper come
admin_portal
Odistributor_portal
.
- Al suo interno, aggiungi shopper come
- Crea regno “inquilino. ”
- Approccio simile: creare un shopper per ogni applicazione distinta.
Ogni regno tiene traccia della propria listing utente. Se l’amministratore dell’inquilino A vuole disabilitare un utente, ciò è fatto solo nell’inquilino un regno, lasciando intatto l’inquilino B.
Creazione di un regno isolato
Cliente isolato per prodotti diversi
Perché così conveniente?
Perché una volta configurati regni e clienti, le attività quotidiane per ogni inquilino sono ben partizionate. Lo employees di Tenant A non può scherzare con la configurazione dell’inquilino B e viceversa.
Cablaggio in .web
Rilevare l’inquilino
Nella maggior parte dei miei progetti, mi affido sottodomini o frontend Impostazioni per capire quale inquilino sta attualmente colpendo l’applicazione, come tenantA.myapp.com
contro tenantB.myapp.com
. Se i sottodomi non sono un’opzione, è possibile passare un’intestazione personalizzata, analizzare un segmento del percorso o memorizzare un identificatore inquilino nelle affermazioni JWT.
var host = context.Request.Host.Host;
var tenant = host.Incorporates("tenantA") ? "tenantA" : "tenantB";
Conservare le configurazioni del regno
Tengo un semplice dizionario o un file JSON che mappa i nomi degli inquilini alle impostazioni di KeyCloak:
public static class MultiTenantAuthOptions
{
public static Dictionary TenantSettings = new()
{
("tenantA") = new TenantConfig
{
RealmName = "tenantA",
AuthorityUrl = "http://localhost:8080/realms/tenantA",
ClientId = "admin_portal",
ClientSecret = "SECRET_A"
},
("tenantB") = new TenantConfig
{
RealmName = "tenantB",
AuthorityUrl = "http://localhost:8080/realms/tenantB",
ClientId = "dist_portal",
ClientSecret = "SECRET_B"
}
};
}
In questo modo, la mia applicazione prende a destra AuthorityUrl
E ClientId
in fase di esecuzione.
Eventi personalizzati per il portatore JWT
ASP.NET Core utilizza normalmente una configurazione statica per il portatore JWT. Ma con Multi-Tenancy, lo prevalco al volo. Per esempio:
public class MultiTenantJwtBearerEvents : JwtBearerEvents
{
public override Process MessageReceived(MessageReceivedContext context)
{
var host = context.Request.Host.Host;
var tenantKey = host.Incorporates("tenantA") ? "tenantA" : "tenantB";
if (MultiTenantAuthOptions.TenantSettings.TryGetValue(tenantKey, out var cfg))
{
context.Choices.Authority = cfg.AuthorityUrl;
context.Choices.TokenValidationParameters.ValidAudience = cfg.ClientId;
}
return base.MessageReceived(context);
}
}
Successivamente, il mio codice può gestire gli accessi da diversi regni senza attrito.
Amministratori specifici del regno
Impostazione dei ruoli di amministrazione
KeyCloak ti consente di dare a ciascun regno il proprio utente amministratore. Mi piace questo perché dà a ciascun inquilino il controllo sulla propria base di utenti, ruoli e regole di sicurezza, senza rischiare la confusione incrociata. I passaggi sono semplici:
- Vai a Gestisci> utenticrea un utente chiamato, diciamo,
realmAdminA
. - Assegna ruoli come
manage-users
,view-realm
e così through, in particolare sotto ilrealm-management
Cliente in quel regno. - Quell’utente ora può svolgere attività di amministrazione solo all’interno del proprio regno.
Le azioni tipiche a livello di amministrazione includono:
- Disabilitare/abilitare gli utenti
- Reimpostare le password
- Gestione dell’appartenenza al gruppo
- Controllo delle sessioni utente e accedere agli utenti
- Configurazione dei requisiti 2FA
Poiché queste autorizzazioni di amministrazione sono espulse in un singolo regno, l’amministratore di un inquilino non può vedere o rompere nulla che appartiene a un altro inquilino. Quella separazione è esattamente ciò di cui hanno bisogno le architetture multi-tenant.
Sessioni di registrazione e utente
KeyCloak registri tutti i tipi di eventi: login, loguut, tentativi non riusciti, reimposta di password, ecc. Questo è ottimo per la conformità e la risoluzione dei problemi. Ogni amministratore del regno può visualizzare i registri rilevanti solo per quel regno.
Gli utenti, dalla loro parte, possono vedere le proprie sessioni attive e finirle se necessario. È semplice e mantiene la responsabilità chiaramente divisa.
Configurare ciò che gli ascoltatori ricevono eventi per il regno.
Configurare ciò che gli eventi utente devono registrare per il regno.
Configurare ciò che gli eventi di amministrazione devono registrare per il regno.
Gli eventi sono file di eventi utente e amministratori in questo regno.
Le sessioni sono sessioni di utenti in questo regno e dei clienti che accedono all’interno della sessione.
Migrazione degli utenti esistenti
Se stai già eseguendo un negozio utente legacy, probabilmente vuoi portare quei dati in KeyCloak. Di solito considero due metodi:
- Migrazione just-in-time (JIT)
- Quando un utente accede per la prima volta, il codice controlla il vecchio database, convalida le credenziali e quindi crea l’utente in KeyCloak.
- Migrazione di massa
- Scrivi uno script che estrae tutti i file degli utenti dal vecchio sistema e chiama l’API REST AMMINIO di KeyCloak per creare tali utenti.
Se si dispone di password hash in un formato non commonplace, è possibile richiedere un reimpostazione della password forzata al primo accesso KeyCloak. In genere è più sicuro che immagazzinare testo in chiaro o scherzare con hashing personalizzato.
Isolamento dei dati in .NET
Anche se KeyCloak Realms si occupa dell’isolamento dell’identità, il tuo Applicazione .NET deve ancora rispettare la multi-tenancy nel livello dei dati. Di solito, mi affido:
- Schemi DB separati o stringhe di connessione separate per inquilino
- Servizi con ambito che iniettano l’ID inquilino corrente e filtra automaticamente le question
- Cache partizionate Quindi non si servono accidentalmente dati memorizzati nella cache dall’inquilino A all’inquilino B
È un approccio a due strati: KeyCloak non garantisce una sovrapposizione di identità e l’applicazione non garantisce una sovrapposizione di dati.
Pensieri finali e migliori pratiche
Nella mia esperienza, l’istituzione di un regno per inquilino semplifica quasi ogni problema relativo alla sicurezza. È facile ragionare, facile da consegnare diritti di amministrazione parziali e diretto a girare nuovi regni man mano che cresci. Alcuni consigli di separazione:
- Automatizza la creazione del regno: Approfitta dell’API REST AMMINIGLIO di KeyCloak o delle sue funzionalità di importazione/esportazione del regno.
- Monitorare attentamente: Utilizzare le metriche combine o gli strumenti esterni di KeyCloak (Prometheus, Grafana) per tenere sotto controllo prestazioni, attività di accesso e potenziali tentativi di forza bruta.
- Guarda il Realm Contare: Se ti aspetti centinaia o migliaia di inquilini, pesare attentamente le spese generali – a volte è necessario raggruppare gli inquilini più piccoli in un singolo regno.
Combinando queste strategie di KeyCloak Realms con il codice .NET consapevole degli inquilini, ho creato piattaforme SaaS che si ridimensionano in modo ordinato mantenendo bloccata la base di utenti di ciascun cliente. Se stai cercando di semplificare la gestione dell’identità multi-tenant su .NET, KeyCloak Realms potrebbe semplicemente salvarti una tonnellata di seccatura.