2016-04-14 14 views
1

Kein Glück, eine vorher gestellte Frage zu diesem Thema zu finden; war nicht ganz sicher, wie es formuliert werden sollte.Wie man einfach einen ganzen (Redis) Client einpackt

Wie auch immer, ich werde mit dem Problem beginnen, das ich versuche zu lösen. In unserer Anwendung werden Daten mit dem npm-Redis-Modul zwischengespeichert. Wir initialisieren einen Kunden und stellen diesen in unserer Geschäftslogik zur Verfügung und nutzen ihn direkt. Jetzt wollen wir jedoch die Daten, die wir cachen, verschlüsseln. Anstatt also die gesamte Verschlüsselungs-/Entschlüsselungslogik in der Hauptgeschäftslogik zu haben, dachte ich, es wäre schöner, wenn wir den Client einfach so wickeln könnten, dass alle Aufrufe einen Verschlüsselungs-/Entschlüsselungsschritt enthalten würden. Das Problem ist, dass der Redis-Client einen ganzen Haufen von exportierten Funktionen hat (set, hset, hmset, setex usw. usw.), so dass es mühsam wäre, jede Funktion einzeln zu überschreiben.

Also, meine Frage ist, gibt es eine Möglichkeit, den gesamten Client zu wickeln? Wenn eine der Funktionen des Clients aufgerufen wird, wird eine Vorverarbeitungsfunktion aufgerufen, die die Verschlüsselung/Entschlüsselung im Voraus durchführt und dann die eigene Funktion des Redis-Clients aufruft.

z.

myClient.foo() 
    call encrypt() 
    call redisClient.foo() 

aber müssen die oben genannten automatisch für jede exportierte Funktion des Redis-Clients auftreten?

Auch dies ist ein frühes Denken, so dass es nicht einmal sinnvoll ist, dies zu tun. Würde bestimmte Verhaltensweisen abhängig von bestimmten Funktionen bestimmen müssen; z.B. welche Anrufe verschlüsseln, und welche entschlüsseln usw. Aber ich nehme an, dass ich mich fragte, ob das oben genannte sogar auf eine saubere Art möglich ist? Selbst für eine einfache generische Funktion wie das Protokollieren jedes Client-Anrufs oder etwas, das nicht funktionsabhängig ist.

Edit: , um zu versuchen zu gehen und zu vereinfachen, was es ist Ich denke an zu tun. Wenn wir die Verschlüsselung aus der Gleichung nehmen. Ist es möglich, einen dynamisch exportierten Funktionsnamen zu haben? So etwas wie die folgenden, mit Ausnahme von „foo“ ist dynamisch und kann verwendet werden, die redisClient exportierte Funktion mit dem gleichen Namen zu nennen:

exports.myClient.foo = function(){ //where foo can be any value? 
    genericFunction(arguments); 
    redisClient[foo].apply(arguments) 
} 
+0

Ich denke, es hängt davon ab, wie sehr Sie sich auf die Gleichzeitigkeitssicherheit verlassen. Wenn Ihr Crypto Wrapper Ihre App einer Konkurrenzsituation aussetzen würde, dann würden Sie den Punkt übersehen. Sie können Lua-Skripte verwenden, aber AFAIK Lua hilft nicht zu viel mit der Verschlüsselung, und Sie müssten jede Methode wie erwähnt umhüllen. Müssen Sie die Daten "in-transport" oder "at-rest" verschlüsseln? – ptrk

+0

Die Verschlüsselung dient zum Ruhen von Daten im Cache. Wir haben den Transport über TLS gesichert, aber wenn der Cache kompromittiert ist, wollen wir den Inhalt verschlüsselt haben. Wir verwenden Azure für unsere Plattform und erwägen die Verwendung von KeyVault-Verschlüsselungsdiensten, sodass die Verschlüsselung auf der Anwendungsseite erfolgen muss. Dies kann sich jedoch ändern, da wir davon ausgehen, dass der KeyVault-Verschlüsselungsansatz eine erhebliche Leistungseinbuße haben könnte, da es sich im Wesentlichen um eine externe HTTP-Anfrage handelt. – Mitch

+2

Beim zweiten Gedanken kann ich keine einfache Möglichkeit sehen, redis _without_ ohne jede Methode getrennt zu wickeln. Sie haben unterschiedliche Parameter und Verhalten, stellen Sie sich die Inkrementierung vor - erhöhen Sie sicher verschlüsselte Daten? Wenn nicht, dann brauchst du den ganzen Turnaround (get-> decrypt-> increment-> encrypt-> put) und behalte es immer noch atomar - dann ist Lua deine einzige Option, denke ich. Wie wäre es, wenn Sie die Verschlüsselung nicht bewusst machen und die Verschlüsselung irgendwo näher an die Geschäftslogik abstrahieren? Vielleicht muss nicht alles so sicher sein? – ptrk

Antwort

0

Was Sie fragen sicherlich möglich ist und was Sie tun müssen, ist nur nehmen einige Zeit, um die Klasse zu erstellen, die den Redis-Client zum Hinzufügen der Verschlüsselung umschließt. Soweit ich weiß, gibt es mit dem Standardmandanten (https://www.npmjs.com/package/redis) keine einfache Methode, um die Eingabe zu modifizieren, bevor sie in redis oder in der Ausgabe gespeichert wird, bevor sie von einer GET-Operation zurückgegeben wird.

Angenommen, Sie verwenden Redis nur mit SET- und GET-Operationen, können Sie so etwas tun.

ich davon aus bin haben Sie Ihre Verschlüsselungslogik in einem bestimmten Modul und dass der Verschlüsselungsalgorithmus ist synchron:

// encryption.js 

"use strict"; 

function Encryption(key) { 
    this.key = key; 
} 

Encryption.prototype.enc(value) { 
    // Encrypts the value using the key and returns it... 
} 

Encryption.prototype.dec(value) { 
    // Decrypts the value using the key and returns it... 
} 

module.exports = Encryption 

Unsere redis Wrapper wie folgt aussehen:

// encryptedRedisClient.js 

"use strict"; 

function EncryptedRedisClient(redisClient, encryption) 
{ 
    this.redisClient = redisClient; 
    this.encryption = encryption; 
} 

EncryptedRedisClient.prototype.get(key, cb) 
{ 
    this.client.get(key, function (err, reply) { 
    if (err) { 
     cb(err); 
    } 

    cb(null, this.encrypt.dec(reply.toString())); 
    }); 
} 

EncryptedRedisClient.prototype.set(key, value, cb) 
{ 
    var encValue = this.encryption.enc(value); 
    this.client.set(key, encValue, cb); 
} 

module.exports = EncryptedRedisClient; 

Schließlich können Sie verwenden der umhüllte Client wie folgt aus:

"use strict"; 

var redis = require('redis'); 
var client = redis.createClient(); // add the needed options here 
var Encryption = require('./encryption'); 
var EncryptedRedisClient = require('./encryptedRedisClient'); 

var encClient = new EncryptedRedisClient(client, new Encryption('some_secret_key')); 

encClient.set(...); 
encClient.get(...); 

ich habe den Code nicht getestet Es könnte also ein paar kleinere Probleme geben, aber das sollte einen guten Anfangspunkt geben.

+0

Dieser Ansatz beinhaltet immer noch das Erstellen einer exportierten Funktion für jede Funktion im Redis-Client (die Get- und Set-Funktionen). Ich suche nach einer Möglichkeit, den Verschlüsselungsaufruf für jede exportierte Funktion im Redis-Client ausführen zu lassen, ohne manuell einen Wrapper für jeden einzelnen schreiben zu müssen. – Mitch

+0

Ja, aber ich denke nicht, dass das Standard-Redis-Modul einen Erweiterungspunkt bietet, um Ihnen einen allgemeineren Ansatz zu ermöglichen. Bedenken Sie auch, dass jede Redis-Operation ihre eigene interne Logik hat und dass die Art und Weise, wie Sie die Informationen verschlüsseln und dann entschlüsseln, sich zwischen den Operationen ändert. Denken Sie nur darüber nach, wie Sie eine INC-Operation verschlüsseln/entschlüsseln können (natürlich nur, wenn Sie auch Zähler verschlüsseln wollen, was keine einfache Annahme ist) ... –

Verwandte Themen