I dati spesso richiedono una sicurezza di fascia alta a quasi tutti i livelli della transazione di dati in modo da soddisfare le politiche di sicurezza, la conformità e le normative governative. La reputazione dell'organizzazione può essere danneggiata in caso di accesso non autorizzato a dati sensibili, quindi il mancato rispetto del mandato delineato.
In questo blog discuteremo di alcune delle misure di sicurezza che puoi adottare in relazione a MongoDB, in particolare concentrandoci sul lato client delle cose.
Scenari in cui è possibile accedere ai dati
Ci sono diversi modi in cui qualcuno può accedere ai tuoi dati MongoDB, eccone alcuni...
- Acquisizione di dati su una rete non sicura. Qualcuno può accedere ai tuoi dati tramite un'API con una rete VPN e sarà difficile rintracciarli. I dati inattivi sono spesso i colpevoli in questo caso.
- Un super utente come un amministratore con accesso diretto. Ciò accade quando non riesci a definire i ruoli utente e le restrizioni.
- Avere accesso ai dati su disco durante la lettura dei database dei file di backup.
- Lettura della memoria del server e dei dati registrati.
- Divulgazione accidentale di dati da parte di un membro del personale.
Categorie di dati MongoDB e modalità di protezione
In generale, qualsiasi sistema di database coinvolge due tipi di dati:
- Dati inattivi:uno che viene archiviato nei file del database
- Dati in transito:uno che viene scambiato tra un client, un server e il database.
MongoDB ha una funzione di crittografia a riposo che crittografa i file di database su disco, impedendo così accesso ai file di database su disco.
I dati in transito su una rete possono essere protetti in MongoDB tramite Transport Encryption utilizzando TLS/SSL crittografando i dati.
Nel caso in cui i dati vengano divulgati accidentalmente da un membro del personale, ad esempio un addetto alla reception sullo schermo del desktop, MongoDB integra il controllo degli accessi basato sui ruoli che consente agli amministratori di concedere e limitare i permessi a livello di raccolta per gli utenti.
I dati trasferiti sul server possono rimanere in memoria e questi approcci non risolvono in alcun momento i problemi di sicurezza contro l'accesso ai dati nella memoria del server. MongoDB ha quindi introdotto la crittografia a livello di campo lato client per crittografare campi specifici di un documento che coinvolgono dati riservati.
Crittografia a livello di campo
MongoDB lavora con documenti che hanno campi definiti. Alcuni campi potrebbero essere richiesti per contenere informazioni riservate come numero di carta di credito, numero di previdenza sociale, dati di diagnosi della pazienza e molto altro.
Field Level Encryption ci consentirà di proteggere i campi e sono accessibili solo da personale autorizzato con le chiavi di decrittazione.
La crittografia può essere eseguita in due modi
- Utilizzo di una chiave segreta. Una singola chiave viene utilizzata sia per la crittografia che per la decrittografia, quindi deve essere presentata all'origine e alla destinazione della trasmissione ma mantenuta segreta da tutte le parti.
- Utilizzo di una chiave pubblica. Utilizza una coppia di chiavi in cui una viene utilizzata per crittografare e l'altra utilizzata per decrittografare
Quando si applica la crittografia a livello di campo, considerare l'utilizzo di una nuova configurazione del database anziché di una esistente.
Crittografia a livello di campo lato client (CSFLE)
Introdotto in MongoDB versione 4.2 Enterprise per offrire agli amministratori di database un adeguamento per crittografare i campi che coinvolgono valori che devono essere protetti. Vale a dire, i dati sensibili vengono crittografati o decifrati dal client e comunicati da e verso il server solo in forma crittografata. Inoltre, anche i super utenti che non dispongono delle chiavi di crittografia, non avranno il controllo su questi campi di dati crittografati.
Come implementare CSFLE
Per poter implementare la crittografia a livello di campo lato client, è necessario quanto segue:
- MongoDB Server 4.2 Enterprise
- MongoDB Compatibile con CSFLE
- Autorizzazioni del file system
- Driver di lingua specifici. (Nel nostro blog useremo Node.js)
La procedura di attuazione prevede:
- Un ambiente di sviluppo locale con un software per l'esecuzione di client e server
- Generazione e convalida delle chiavi di crittografia.
- Configurazione del client per la crittografia automatica a livello di campo
- Durante le operazioni in termini di query dei campi crittografati.
Implementazione CSFLE
CSFLE utilizza la strategia di crittografia della busta in base alla quale le chiavi di crittografia dei dati vengono crittografate con un'altra chiave nota come chiave principale. L'applicazione client crea una chiave master che viene archiviata nel provider di chiavi locali essenzialmente nel file system locale. Tuttavia, questo approccio di archiviazione non è sicuro, quindi in produzione, si consiglia di configurare la chiave in un sistema di gestione delle chiavi (KMS) che archivia e decodifica le chiavi di crittografia dei dati in remoto.
Dopo che le chiavi di crittografia dei dati sono state generate, vengono archiviate nella raccolta del vault nello stesso set di repliche MongoDB dei dati crittografati.
Crea chiave principale
Nel nodo js, dobbiamo generare una chiave master di 96 byte gestita localmente e scriverla in un file nella directory da cui viene eseguito lo script principale:
$npm install fs && npm install crypto
Quindi nello script:
const crypto = require(“crypto”)
const fs = require(“fs”)
try{
fs.writeFileSync(‘masterKey.txt’, crypto.randomBytes(96))
}catch(err){
throw err;
}
Crea una chiave di crittografia dei dati
Questa chiave è archiviata in una raccolta di credenziali delle chiavi in cui i client abilitati CSFLE possono accedere alla chiave per la crittografia/decrittografia. Per generarne uno, hai bisogno di quanto segue:
- Chiave principale gestita localmente
- Connessione al tuo database ovvero la stringa di connessione MongoDB
- Spazio dei nomi Key Vault (database e raccolta)
Passaggi per generare la chiave di crittografia dei dati
-
Leggi la chiave master locale generata prima
const localMasterKey = fs.readFileSync(‘./masterKey.txt’);
-
Specificare le impostazioni del provider del servizio di gestione delle chiavi che verranno utilizzate dal client per rilevare la chiave principale.
const kmsProvider = {
local: {
key: localMasterKey
}
}
-
Creazione della chiave di crittografia dei dati. È necessario creare un client con la stringa di connessione MongoDB e la configurazione dello spazio dei nomi dell'insieme di credenziali delle chiavi. Diciamo che avremo un database chiamato users e al suo interno una collezione di keyVault. Devi prima installare uuid-base64 eseguendo il comando
$ npm install uuid-base64
Quindi nel tuo script
const base64 = require('uuid-base64');
const keyVaultNamespace = 'users.keyVaul';
const client = new MongoClient('mongodb://localhost:27017', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
async function createKey() {
try {
await client.connect();
const encryption = new ClientEncryption(client, {
keyVaultNamespace,
kmsProvider,
});
const key = await encryption.createDataKey('local');
const base64DataKeyId = key.toString('base64');
const uuidDataKeyId = base64.decode(base64DataKeyId);
console.log('DataKeyId [UUID]: ', uuidDataKeyId);
console.log('DataKeyId [base64]: ', base64DataKeyId);
} finally {
await client.close();
}
}
createKey();
Ti verrà quindi presentato un risultato simile a
DataKeyId [UUID]: ad4d735a-44789-48bc-bb93-3c81c3c90824
DataKeyId [base64]: 4K13FkSZSLy7kwABP4HQyD==
Il client deve disporre delle autorizzazioni ReadWrite per lo spazio dei nomi dell'insieme di credenziali delle chiavi specificato
-
Per verificare che la chiave di crittografia dei dati sia stata creata
const client = new MongoClient('mongodb://localhost:27017', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
async function checkClient() {
try {
await client.connect();
const keyDB = client.db(users);
const keyColl = keyDB.collection(keyVault);
const query = {
_id: ‘4K13FkSZSLy7kwABP4HQyD==’,
};
const dataKey = await keyColl.findOne(query);
console.log(dataKey);
} finally {
await client.close();
}
}
checkClient();
Dovresti ricevere un risultato del genere
{
_id: Binary {
_bsontype: 'Binary',
sub_type: 4,
position: 2,
buffer: <Buffer 68 ca d2 10 16 5d 45 bf 9d 1d 44 d4 91 a6 92 44>
},
keyMaterial: Binary {
_bsontype: 'Binary',
sub_type: 0,
position: 20,
buffer: <Buffer f1 4a 9f bd aa ac c9 89 e9 b3 da 48 72 8e a8 62 97 2a 4a a0 d2 d4 2d a8 f0 74 9c 16 4d 2c 95 34 19 22 05 05 84 0e 41 42 12 1e e3 b5 f0 b1 c5 a8 37 b8 ... 110 more bytes>
},
creationDate: 2020-02-08T11:10:20.021Z,
updateDate: 2020-02-08T11:10:25.021Z,
status: 0,
masterKey: { provider: 'local' }
}
I dati del documento restituiti includono:ID chiave di crittografia dei dati (UUID), chiave di crittografia dei dati in forma crittografata, informazioni sul provider del servizio di gestione delle chiavi master e metadati come il giorno di creazione.
Specifica dei campi da crittografare utilizzando lo schema JSON
Un'estensione JSON Schema viene utilizzata dai driver MongoDB per configurare la crittografia e la decrittografia lato client automatiche dei campi di documenti specificati in una raccolta. La configurazione CSFLE per questo schema richiederà:l'algoritmo di crittografia da utilizzare durante la crittografia di ogni campo, una o tutte le chiavi di crittografia crittografate con la chiave master CSFLE e il tipo BSON di ciascun campo.
Tuttavia, questo schema JSON CSFLE non supporta la convalida dei documenti, altrimenti eventuali istanze di convalida causeranno la generazione di un errore da parte del client.
I client che non sono configurati con lo schema JSON lato client appropriato possono essere limitati dalla scrittura di dati non crittografati in un campo utilizzando lo schema JSON lato server.
Ci sono principalmente due algoritmi di crittografia:casuale e deterministico.
Definiremo alcune chiavi encryptMetadata a livello di root dello schema JSON e la configureremo con i campi da crittografare definendoli nel campo delle proprietà dello schema, quindi potranno ereditare questa chiave di crittografia .
{
"bsonType" : "object",
"encryptMetadata" : {
"keyId" : // keyId generated here
},
"properties": {
// field schemas here
}
}
Supponiamo che tu voglia crittografare un campo del numero di conto bancario, faresti qualcosa del tipo:
"bankAccountNumber": {
"encrypt": {
"bsonType": "int",
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
}
}
A causa dell'elevata cardinalità e del campo interrogabile, utilizziamo l'approccio deterministico. Campi sensibili come gruppo sanguigno che hanno un piano di query basso e una cardinalità bassa possono essere crittografati utilizzando l'approccio casuale.
I campi array dovrebbero utilizzare la crittografia casuale con CSFLE per migliorare la crittografia automatica per tutti gli elementi.
Applicazione Mongocryptd
Installata in MongoDB Enterprise Service 4.2 e versioni successive, questa è un'applicazione di crittografia separata che automatizza la crittografia a livello di campo lato client. Ogni volta che viene creato un client abilitato per CSFLE, questo servizio viene avviato automaticamente per impostazione predefinita su:
- Convalida le istruzioni di crittografia descritte nello schema JSON, rileva quali campi devono essere crittografati nelle operazioni di throughput.
- Impedisci l'esecuzione di operazioni non supportate sui campi crittografati.
Per inserire i dati faremo la normale query di inserimento e il documento risultante avrà dati di esempio di seguito rispetto al campo del conto bancario.
{
…
"bankAccountNumber":"Ac+ZbPM+sk7gl7CJCcIzlRAQUJ+uo/0WhqX+KbTNdhqCszHucqXNiwqEUjkGlh7gK8pm2JhIs/P3//nkVP0dWu8pSs6TJnpfUwRjPfnI0TURzQ==",
…
}
Quando un personale autorizzato esegue una query, il conducente decrittograferà questi dati e li restituirà in un formato leggibile, ad esempio
{
…
"bankAccountNumber":43265436456456456756,
…
}
Nota: non è possibile eseguire query sui documenti in un campo crittografato in modo casuale a meno che non utilizzi un altro campo per trovare il documento che contiene un'approssimazione dei dati del campo crittografati in modo casuale.
Conclusione
La sicurezza dei dati dovrebbe essere considerata a tutti i livelli rispetto a quelli inattivi e in transito. MongoDB Enterprise 4.2 Server offre agli sviluppatori una finestra per crittografare i dati dal lato client utilizzando la crittografia a livello di campo lato client, proteggendo così i dati dai provider host del database e l'accesso alla rete non sicuro. CSFLE utilizza la crittografia della busta in cui una chiave master viene utilizzata per crittografare le chiavi di crittografia dei dati. La chiave maestra dovrebbe quindi essere tenuta al sicuro utilizzando strumenti di gestione delle chiavi come il sistema di gestione delle chiavi.