2017-07-03 38 views
0

ノードJS SDKからKMS暗号化を使用してファイルをAWS S3にアップロードする方法を理解できません。私は403:Access Deniedエラーを受けています。 AWS S3からKMSを使用してファイルを取得できます。ノードjs SDKでAWS KMS暗号化を使用する方法

私はhttps://github.com/gilt/node-s3-encryption-client

メインクラス

からのコードのほとんどを再利用しています
var fs = require('fs'), 
    AWS = require('aws-sdk'), 
    crypt = require("./crypt"), 
    kms, 
    s3; 

const metadataCipherAlgorithm = 'cipher-algorithm', 
     metadataDecryptedEncoding = 'decrypted-encoding' 
     metadataKmsKeyName = 'x-amz-key'; 


/** 
* Constructor - Initializes S3 sdk connection 
*/ 
function S3FileStreamer(key, secret, region) { 
    if (region) { 
     AWS.config.region = region; 
    } 
    //set credentials if passed in 
    if (key && secret) { 
     AWS.config.update({accessKeyId: key, secretAccessKey: secret}) 
    } 
    s3 = new AWS.S3({signatureVersion: "v4"}); 
    kms = new AWS.KMS({apiVersion: '2014-11-01'}); 
} 

S3FileStreamer.prototype.uploadFile = function(bucket, key, kmsKey, filename, onComplete) { 
    var params = { 
     Bucket: bucket, 
     Key: key, 
     Body: fs.readFileSync(filename), 
     ContentType: getMimeType(filename) 
    }; 

    params.KmsParams = { 
     KeyId: kmsKey, 
     KeySpec: 'AES_256' 
    } 

    kmsUpload(params, function(err, data) { 
     if (err) onComplete(err, null); 
     else { 
      onComplete(err, data); 
     } 
    }); 
}; 

function kmsUpload(params, callback) { 
    var kmsParams = params.KmsParams 
    if (kmsParams && kmsParams.KeyId) { 
    kms.generateDataKey(kmsParams, function(err, kmsData) { 
     if (err) { 
     callback(err, null); 
     } else { 
     var helper = new crypt.Helper(kmsData.Plaintext.toString('base64'), {algorithm: params.CipherAlgorithm, decryptedEncoding: params.DecryptedEncoding}); 
     params.Body = helper.encrypt(params.Body); 
     params.Metadata = params.Metadata || {}; 
     params.Metadata[metadataKmsKeyName] = kmsData.CiphertextBlob.toString('base64'); 
     if (params.CipherAlgorithm) params.Metadata[metadataCipherAlgorithm] = params.CipherAlgorithm; 
     if (params.DecryptedEncoding) params.Metadata[metadataDecryptedEncoding] = params.DecryptedEncoding; 
     putObject(params, callback); 
     } 
    }) 
    } else { 
    putObject(params, callback); 
    } 
} 

function putObject(params, callback) { 
    delete params.KmsParams; 
    delete params.CipherAlgorithm; 
    delete params.DecryptedEncoding; 
    s3.putObject(params, callback); 
} 

墓所クラス

var crypto = require('crypto'); 

/* 
    options: 
    algorithm: Anything from crypto.getCiphers() 
    decryptedEncoding: 'utf8', 'ascii', or 'binary' 
    outputEncoding: 'binary', 'base64', or 'hex' 
*/ 
exports.Helper = function(password, options) { 
    this.password = password; 
    options = options || {}; 
    this.algorithm = options.algorithm || 'aes-256-cbc'; 
    this.decryptedEncoding = options.decryptedEncoding || 'utf8'; 
    this.encryptedEncoding = options.encryptedEncoding || 'base64'; 
} 

exports.Helper.prototype.encrypt = function(unencrypted) { 
    var cipher = crypto.createCipher(this.algorithm, this.password); 
    return cipher.update(unencrypted, this.decryptedEncoding, this.encryptedEncoding) + cipher.final(this.encryptedEncoding); 
} 

exports.Helper.prototype.decrypt = function(encrypted) { 
    var decipher = crypto.createDecipher(this.algorithm, this.password); 
    return decipher.update(encrypted, this.encryptedEncoding, this.decryptedEncoding) + decipher.final(this.decryptedEncoding); 
} 

私がここで行方不明です何か、する必要があります余分なメタデータタグはあります設定される?

kms generateDataKeyメソッドに渡されるkeyIdパラメータは、何らかの一意の形式であるはずですか?私は単に私の鍵を渡すだけです。

+0

どこからファイルを読み取っていますか?最初にソースからファイルを読み取る権限があるかどうかを確認してください。おそらく、使用している役割にS3バケットに対する更新書き込み許可があるかどうかを確認してください。 – Ali

答えて

1

権限の確認に関するもう1つの回答は確かに間違いありません。 AES GCM暗号化アルゴリズムを使用してS3オブジェクトをデコードする方法の良い例を見つけるのは苦労しました。私はこのコードをaws ruby​​ sdkに基づいて動作させることができました(私はnode-s3-encryption-clientが少し古いと感じました)。

/** 
* Decrypt s3 file data 
* @param {object} objectData result of s3 get call 
* @param {Function} callback function(err, data) returns error or decrypted data 
*/ 
function decrypt(objectData, callback) { 
    var metadata = objectData.Metadata || {}; 
    var kmsKeyBase64 = metadata['x-amz-key-v2']; 
    var iv = metadata['x-amz-iv']; 
    var tagLen = (metadata['x-amz-tag-len'] || 0)/8; 
    var algo = metadata['x-amz-cek-alg']; 
    var encryptionContext = JSON.parse(metadata['x-amz-matdesc']); 

    switch (algo) { 
     case 'AES/GCM/NoPadding': 
      algo = 'aes-256-gcm'; 
      break; 
     case 'AES/CBC/PKCS5Padding': 
      algo = 'aes-256-cbc'; 
      break; 
     default: 
      callback(new Error('Unsupported algorithm: ' + algo), null); 
      return; 
    } 

    if (typeof (kmsKeyBase64) === 'undefined') { 
     callback(new Error('Missing key in metadata'), null); 
     return; 
    } 

    var kmsKeyBuffer = new Buffer(kmsKeyBase64, 'base64'); 
    kms.decrypt({ 
     CiphertextBlob: kmsKeyBuffer, 
     EncryptionContext: encryptionContext 
    }, function(err, kmsData) { 
     if (err) { 
      callback(err, null); 
     } else { 
      var decipher = crypto.createDecipheriv(algo, 
                kmsData.Plaintext, 
                new Buffer(iv, 'base64')); 

      if (tagLen !== 0) { 
       // the tag is appended to the data buffer 
       var tag = objectData.Body.slice(-tagLen); 
       decipher.setAuthTag(tag); 
      } 
      var data = objectData.Body.slice(0,-tagLen); 

      var dec = decipher.update(data, 'binary', 'utf8'); 
      dec += decipher.final('utf8'); 

      console.log("Decoded:", dec); 
      callback(null, dec); 
     } 
    }); 
} 
0

ありがとうございました。私は私の質問の解決策を考え出しました。

私はaws-sdkノードモジュールを使用して戻り、node-s3-encryption-clientモジュールから取得したすべてのコードを取り出しました。

KMS暗号化を使用してAmazon S3にファイルを正常にアップロードするには、putObjectメソッドにparamsオブジェクトを渡す前に2つのパラメータを追加する必要がありました。これらのパラメータは、以下に示すようにServerSideEncryptionSSEKMSKeyIdでした。それは今働きます!

var params = { 
    Bucket: bucket, 
    Key: key, 
    Body: fs.readFileSync(filename), 
    ContentType: getMimeType(filename), 
    ServerSideEncryption: 'aws:kms', 
    SSEKMSKeyId: kmsKey 
}; 

s3.putObject(params, function(err, data) { 
    if (err) { 
     console.log(err); 
    } else { 
     console.log(data); 
}); 
関連する問題