2016-04-14 11 views
1

これについて以前に質問されたことはありません。それをどのようにフレーズするかについて完全には分かっていなかった。(Redis)クライアント全体を簡単にラップする方法

とにかく、解決しようとしている問題から始めます。 私たちのアプリケーションでは、npm redisモジュールを使ってRedisにデータをキャッシュしています。クライアントを初期化してビジネスロジックで利用可能にし、直接使用します。 しかし、私たちがキャッシュするデータを暗号化する必要があります。したがって、すべての暗号化/復号化ロジックをメインのビジネスロジックに入れるのではなく、すべての呼び出しに暗号化/復号化のステップが含まれるようにクライアントを単純にラップすることができればより良いと思っていました。 問題は、Redisクライアントが、エクスポートされた関数(set、hset、hmset、setexなどなど)全体をヒープしているため、個々の関数を個別にオーバーライド/ラップするのが苦労することです。

私の質問は、クライアント全体を包む方法があるということですか?そのため、クライアントの関数のいずれかが呼び出された場合、あらかじめ暗号化/復号化を実行してから、クライアントの独自の関数を呼び出す前処理関数が呼び出されます。

など。

ただし、上記の内容は、redisクライアントのエクスポートされた機能ごとに自動的に発生しますか?

これもやはり初期の考え方なので、これを行うのは意味がないかもしれません。特定の機能に依存する特定の動作を決定する必要があります。例えば暗号化を呼び出し、それを復号化する。 しかし、上記のことがきれいな方法で可能かどうか疑問に思っていたと思いますか?たとえ各クライアント呼び出しのログや関数に依存しない単純な汎用関数であっても。

編集: 私がやっていることを試してみようと思っています。 私たちは方程式の暗号化を取る場合。 動的にエクスポートされた関数名を持つことは可能ですか? 「foo」という除き、次のような 何か、動的であり、同じ名前の関数をエクスポートしredisClientを呼び出すために使用することができます:

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

私は、あなたが並行性の安全性にどのくらい依存しているかにかかっていると思います。あなたの暗号化ラッパーが競合状態にあなたのアプリを公開するならば、あなたはポイントを逃すでしょう。あなたはLuaスクリプトを使うことができますが、AFAIK Luaは暗号化にあまり役立たず、あなたが言及したようにそれぞれの方法をラップする必要があります。あなたはデータを "輸送中"または "休憩中"で暗号化する必要がありますか? – ptrk

+0

暗号化は、キャッシュ内のデータを休止するためのものです。トランスポートはTLSで保護されていますが、キャッシュが侵害された場合は、コンテンツを暗号化したいと考えています。 Azureをプラットフォームに使用しており、KeyVault暗号化サービスを検討しているため、アプリケーション側で暗号化を行う必要があります。これは、KeyVaultの暗号化アプローチが本質的に外部のhttpリクエストであるため、重要なパフォーマンスヒットを持つ可能性があると推測しているので、変更される可能性があります。 – Mitch

+2

2番目の考えでは、それぞれのメソッドを別々に扱うことなくredisを包み込む簡単な方法はありません。彼らはさまざまなパラメータと動作を持ち、インクリメントを想像してください - 暗号化されたデータを安全に増やしますか?そうでなければ、あなたは完全な処理(get-> decrypt-> increment-> encrypt-> put)を必要とし、それでもアトミックなままにしておいてください。どのように赤字を認識せずに、ビジネスロジックに近いところで暗号化を抽象化するのはどうでしょうか?おそらくそれのすべてがこの安全なものである必要はないでしょうか? – ptrk

答えて

0

あなたが求めているものは確かに可能であり、何をする必要がちょうど取るされますRedisクライアントをラップして暗号化を追加するクラスを作成することがあります。私が知る限り、既定のクライアント(https://www.npmjs.com/package/redis)を使用すると、入力がGET操作から返される前にredisまたは出力に格納される前に入力を変更できる簡単な方法はありません。

SETとGET操作でのみredisを使用していると仮定すると、このようなことができます。

私は、暗号化アルゴリズムが同期していることをあなたが特定のモジュールであなたの暗号化ロジックを持っていると仮定しています:

// 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 

当社のRedisのラッパーは次のようになります。

// 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; 

最後にあなたが使用することができますこのようなラップクライアント:

"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(...); 

私はコードをテストしていません少し問題があるかもしれませんが、これはかなり良い出発点を与えるはずです。

+0

このアプローチでは、依然として、レディス・クライアントの各関数(getおよびset関数)にエクスポートされた関数を作成します。私は暗号化呼び出しを、それぞれのラッパーを手作業で書く必要なく、redisクライアントのエクスポートされたすべての関数で発生させる方法を探しています。 – Mitch

+0

はい、私はデフォルトのRedisモジュールが拡張ポイントを提供しているとは思わないので、より一般的なアプローチを使用できます。また、すべてのredis操作には独自の内部ロジックがあり、情報を暗号化して解読する方法が操作間で分かりやすく変化することにも注意してください。ちょうどあなたがINC操作を暗号化/復号化する方法について考えてください(もちろん、カウンタを暗号化したい場合は、簡単な仮定ではありません)... –

関連する問題