अमेज़ॅन S3 डायरेक्ट फ़ाइल क्लाइंट ब्राउज़र से अपलोड - निजी कुंजी प्रकटीकरण


159

मैं किसी भी सर्वर-साइड कोड के बिना केवल जावास्क्रिप्ट का उपयोग करके REST एपीआई के माध्यम से ग्राहक मशीन से अमेज़न एस 3 पर एक सीधा फ़ाइल अपलोड लागू कर रहा हूं। सभी ठीक काम करते हैं लेकिन एक बात मुझे चिंतित कर रही है ...

जब मैं Amazon S3 REST API के लिए एक अनुरोध भेजता हूं, तो मुझे अनुरोध पर हस्ताक्षर करने और हस्ताक्षर करने की आवश्यकता है Authentication हेडर । हस्ताक्षर बनाने के लिए, मुझे अपनी गुप्त कुंजी का उपयोग करना चाहिए। लेकिन सभी चीजें क्लाइंट साइड पर होती हैं, इसलिए, गुप्त कुंजी को आसानी से पृष्ठ स्रोत से प्रकट किया जा सकता है (भले ही मैं अपने स्रोतों को बाधित / एन्क्रिप्ट करता हूं)।

इससे मैं किस तरह निपट सकता हूं? और क्या यह एक समस्या है? हो सकता है कि मैं विशिष्ट निजी कुंजी उपयोग को केवल एक विशिष्ट CORS उत्पत्ति से REST API कॉल तक सीमित कर सकता हूं और केवल PUT और POST विधियों या केवल S3 और विशिष्ट बाल्टी की कुंजी लिंक कर सकता हूं? हो सकता है कि एक और प्रमाणीकरण विधियां हों?

"सर्वर रहित" समाधान आदर्श है, लेकिन मैं कुछ सर्वरसाइड प्रसंस्करण को शामिल करने पर विचार कर सकता हूं, अपने सर्वर पर फ़ाइल अपलोड करने को छोड़कर और फिर S3 में भेज सकता हूं।


7
बहुत सरल: किसी भी रहस्य को ग्राहक-पक्ष में न रखें। अनुरोध पर हस्ताक्षर करने के लिए आपको एक सर्वर शामिल करना होगा।
रे निकोलस

1
आपको यह भी पता चलेगा कि इन अनुरोधों पर हस्ताक्षर करना और आधार -64 एन्कोडिंग बहुत आसान सर्वर-साइड है। यह यहाँ एक सर्वर को शामिल करने के लिए अनुचित नहीं लगता है। मैं समझ सकता हूँ कि सभी फाइल बाइट्स को सर्वर पर नहीं भेजना चाहता और फिर S3 तक, लेकिन अनुरोध क्लाइंट-साइड पर हस्ताक्षर करने के लिए बहुत कम लाभ है, खासकर जब से कि क्लाइंट-साइड करना थोड़ा चुनौतीपूर्ण और संभावित धीमा होगा (जावास्क्रिप्ट में)।
रे निकोलस

5
यह 2016 है, क्योंकि सर्वर रहित आर्किटेक्चर काफी लोकप्रिय हो गया है, एसडब्ल्यू 3 लैम्ब्डा की मदद से सीधे एस 3 में फाइल अपलोड करना संभव है। इसी तरह के एक प्रश्न के लिए मेरा जवाब देखें: stackoverflow.com/a/40828683/2504317 मूल रूप से आपके पास प्रत्येक फ़ाइल के लिए अपलोड करने में सक्षम API पर हस्ताक्षर करने वाले URL के रूप में एक लैम्ब्डा फ़ंक्शन होगा, और आपके क्लीएड-साइड जावास्क्रिप्ट बस एक HTTP PUT करें पूर्व-हस्ताक्षरित URL। मैंने ऐसा करने के लिए एक Vue कंपोनेंट लिखा है, S3 अपलोड संबंधित कोड पुस्तकालय अज्ञेयवादी हैं, एक नज़र डालें और विचार प्राप्त करें।
केएफ लिन

किसी भी S3 बाल्टी में HTTP / S POST अपलोड के लिए एक और 3 पार्टी। JS3Upload शुद्ध HTML5: jfileupload.com/products/js3upload-html5/index.html
JFU

जवाबों:


215

मुझे लगता है कि आप जो चाहते हैं वह POST का उपयोग करके ब्राउज़र-आधारित अपलोड है।

मूल रूप से, आपको सर्वर-साइड कोड की आवश्यकता होती है, लेकिन यह सब कुछ हस्ताक्षरित नीतियों को उत्पन्न करता है। क्लाइंट-साइड कोड पर हस्ताक्षरित नीति होने के बाद, यह आपके सर्वर से गुजरने वाले डेटा के बिना PO3 को सीधे S3 में अपलोड कर सकता है।

यहाँ आधिकारिक डॉक्टर लिंक हैं:

आरेख: http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingHTTPPOST.html

उदाहरण कोड: http://docs.aws.amazon.com/AmazonS3/latest/dev/HTTPPOSTExam.net.html

हस्ताक्षरित नीति इस तरह से आपके html में जाएगी:

<html>
  <head>
    ...
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    ...
  </head>
  <body>
  ...
  <form action="http://johnsmith.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
    Key to upload: <input type="input" name="key" value="user/eric/" /><br />
    <input type="hidden" name="acl" value="public-read" />
    <input type="hidden" name="success_action_redirect" value="http://johnsmith.s3.amazonaws.com/successful_upload.html" />
    Content-Type: <input type="input" name="Content-Type" value="image/jpeg" /><br />
    <input type="hidden" name="x-amz-meta-uuid" value="14365123651274" />
    Tags for File: <input type="input" name="x-amz-meta-tag" value="" /><br />
    <input type="hidden" name="AWSAccessKeyId" value="AKIAIOSFODNN7EXAMPLE" />
    <input type="hidden" name="Policy" value="POLICY" />
    <input type="hidden" name="Signature" value="SIGNATURE" />
    File: <input type="file" name="file" /> <br />
    <!-- The elements after this will be ignored -->
    <input type="submit" name="submit" value="Upload to Amazon S3" />
  </form>
  ...
</html>

ध्यान दें कि FORM क्रिया सीधे S3 में फ़ाइल भेज रही है - आपके सर्वर के माध्यम से नहीं।

अपने उपयोगकर्ताओं की हर बार एक एक फ़ाइल अपलोड करना चाहता है, आपके द्वारा बनाए गए हैं POLICYऔर SIGNATUREअपने सर्वर पर। आप उपयोगकर्ता के ब्राउज़र पर पृष्ठ वापस करते हैं। उपयोगकर्ता आपके सर्वर से गुजरे बिना सीधे S3 में फ़ाइल अपलोड कर सकता है।

जब आप पॉलिसी पर हस्ताक्षर करते हैं, तो आप आम तौर पर कुछ मिनटों के बाद पॉलिसी को समाप्त कर देते हैं। यह आपके उपयोगकर्ताओं को अपलोड करने से पहले आपके सर्वर से बात करने के लिए मजबूर करता है। इससे यदि आप चाहें तो अपलोड को मॉनिटर और सीमित कर सकते हैं।

आपके सर्वर से या उसके पास जाने वाला एकमात्र डेटा हस्ताक्षरित URL है। आपकी गुप्त कुंजियाँ सर्वर पर गुप्त रहती हैं।


14
कृपया ध्यान दें कि यह हस्ताक्षर v2 का उपयोग करता है जिसे जल्द ही v4 द्वारा प्रतिस्थापित किया जाएगा: docs.aws.amazon.com/AmazonS3/latest/API/…
Jörn Berkefeld

9
${filename}कुंजी नाम में जोड़ने के लिए बहुत सुनिश्चित करें , इसलिए उपरोक्त उदाहरण के लिए, user/eric/${filename}बस के बजाय user/eric। यदि user/ericपहले से विद्यमान फ़ोल्डर है, तो अपलोड चुपचाप विफल हो जाएगा (आप भी success_action_redirect पर पुनर्निर्देशित हो जाएंगे) और अपलोड की गई सामग्री नहीं होगी। यह सोचकर एक घंटे बिताए कि यह एक अनुमति मुद्दा था।
बालिंट एर्डी

यदि आप इस विधि को करने से समयबाह्य प्राप्त करते हैं, तो आप उसे कैसे परिचालित करने की अनुशंसा करेंगे?
ट्रिप

1
@Trip चूंकि ब्राउज़र S3 में फ़ाइल भेज रहा है, आपको जावास्क्रिप्ट में समयबाह्य का पता लगाने और अपने आप को पुनः प्रयास करने की आवश्यकता होगी।
गुप्तमी

@ सेक्रेक्माइक जिसमें एक अनंत लूप चक्र की तरह गंध आती है। जैसा कि टाइमआउट 10 / mbs से अधिक किसी भी फाइल के लिए अनिश्चित काल तक पुनरावृत्ति करने वाला है।
ट्रिप

40

आप यह कर सकते हैं AWS S3 Cognito इस लिंक को यहाँ देखें:

http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/browser-examples.html#Amazon_S3

इस कोड को भी आज़माएं

बस क्षेत्र, IdentityPoolId और आपका बकेट नाम बदलें

<!DOCTYPE html>
<html>

<head>
    <title>AWS S3 File Upload</title>
    <script src="https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js"></script>
</head>

<body>
    <input type="file" id="file-chooser" />
    <button id="upload-button">Upload to S3</button>
    <div id="results"></div>
    <script type="text/javascript">
    AWS.config.region = 'your-region'; // 1. Enter your region

    AWS.config.credentials = new AWS.CognitoIdentityCredentials({
        IdentityPoolId: 'your-IdentityPoolId' // 2. Enter your identity pool
    });

    AWS.config.credentials.get(function(err) {
        if (err) alert(err);
        console.log(AWS.config.credentials);
    });

    var bucketName = 'your-bucket'; // Enter your bucket name
    var bucket = new AWS.S3({
        params: {
            Bucket: bucketName
        }
    });

    var fileChooser = document.getElementById('file-chooser');
    var button = document.getElementById('upload-button');
    var results = document.getElementById('results');
    button.addEventListener('click', function() {

        var file = fileChooser.files[0];

        if (file) {

            results.innerHTML = '';
            var objKey = 'testing/' + file.name;
            var params = {
                Key: objKey,
                ContentType: file.type,
                Body: file,
                ACL: 'public-read'
            };

            bucket.putObject(params, function(err, data) {
                if (err) {
                    results.innerHTML = 'ERROR: ' + err;
                } else {
                    listObjs();
                }
            });
        } else {
            results.innerHTML = 'Nothing to upload.';
        }
    }, false);
    function listObjs() {
        var prefix = 'testing';
        bucket.listObjects({
            Prefix: prefix
        }, function(err, data) {
            if (err) {
                results.innerHTML = 'ERROR: ' + err;
            } else {
                var objKeys = "";
                data.Contents.forEach(function(obj) {
                    objKeys += obj.Key + "<br>";
                });
                results.innerHTML = objKeys;
            }
        });
    }
    </script>
</body>

</html>

अधिक जानकारी के लिए, कृपया जांचें - जीथब

क्या यह कई छवियों का समर्थन करता है?
user2722667

@ user2722667 हाँ यह करता है।
जूमलर

@Joomler हाय धन्यवाद, लेकिन मैं फ़ायरफ़ॉक्स पर इस मुद्दे का सामना कर रहा हूँ RequestTimeout सर्वर के लिए आपका सॉकेट कनेक्शन टाइमआउट अवधि के भीतर से पढ़ा या लिखा नहीं गया था। निष्क्रिय कनेक्शन बंद हो जाएंगे और फ़ाइल S3 पर अपलोड नहीं होती है। क्या आप कृपया मेरी मदद कर सकते हैं कि मैं इस मुद्दे को कैसे ठीक कर सकता हूं। धन्यवाद
usama

1
@ गुमा आप जीथुब में मुद्दे को खोल सकते हैं क्योंकि मुद्दा मेरे लिए स्पष्ट नहीं है
जूलर

@ जूमर को देर से जवाब देने के लिए खेद है कि मैंने GitHub में एक मुद्दा खोला है कृपया इस धन्यवाद पर एक नज़र डालें। github.com/aws/aws-sdk-php/issues/1332
usama

16

आप कह रहे हैं कि आप "सर्वर रहित" समाधान चाहते हैं। लेकिन इसका मतलब है कि आपके पास लूप में "अपना" कोड डालने की कोई क्षमता नहीं है। (नोट: एक बार जब आप किसी ग्राहक को अपना कोड देते हैं, तो यह "उनका" कोड होता है।) नीचे कॉर्स को बंद करने से मदद नहीं मिलती है: लोग आसानी से एक गैर-वेब-आधारित टूल (या वेब-आधारित प्रॉक्सी) लिख सकते हैं जो जोड़ता है अपने सिस्टम का दुरुपयोग करने के लिए सही CORS हैडर।

बड़ी समस्या यह है कि आप विभिन्न उपयोगकर्ताओं के बीच अंतर नहीं कर सकते। आप एक उपयोगकर्ता को उसकी फ़ाइलों को सूचीबद्ध / एक्सेस करने की अनुमति नहीं दे सकते, लेकिन दूसरों को ऐसा करने से रोक सकते हैं। यदि आप दुर्व्यवहार का पता लगाते हैं, तो कुंजी को बदलने के अलावा आप इसके बारे में कुछ भी नहीं कर सकते हैं। (कौन सा हमलावर संभवत: बस फिर से मिल सकता है।)

आपका सबसे अच्छा दांव अपने जावास्क्रिप्ट क्लाइंट के लिए एक कुंजी के साथ "IAM उपयोगकर्ता" बनाना है। केवल इसे केवल एक बाल्टी तक लिखने के लिए पहुँच दें। (लेकिन आदर्श रूप से, ListBucket ऑपरेशन को सक्षम न करें, जो हमलावरों के लिए इसे और अधिक आकर्षक बना देगा।)

यदि आपके पास एक सर्वर (यहां तक ​​कि $ 20 / माह में एक सरल माइक्रो उदाहरण) है, तो आप वास्तविक समय में दुरुपयोग की निगरानी / रोकथाम करते हुए अपने सर्वर पर कुंजियों पर हस्ताक्षर कर सकते हैं। सर्वर के बिना, आप जो सबसे अच्छा कर सकते हैं वह समय-समय पर दुरुपयोग के बाद की निगरानी के लिए होता है। यहाँ मैं क्या करूँगा:

1) समय-समय पर उस IAM उपयोगकर्ता के लिए कुंजी घुमाएँ: हर रात, उस IAM उपयोगकर्ता के लिए एक नई कुंजी उत्पन्न करें, और सबसे पुरानी कुंजी को बदलें। चूंकि 2 कुंजी हैं, प्रत्येक कुंजी 2 दिनों के लिए मान्य होगी।

2) S3 लॉगिंग सक्षम करें, और हर घंटे लॉग डाउनलोड करें। "बहुत सारे अपलोड" और "बहुत सारे डाउनलोड" पर अलर्ट सेट करें। आप कुल फ़ाइल आकार और अपलोड की गई फ़ाइलों की संख्या दोनों की जांच करना चाहेंगे। और आप दोनों वैश्विक योगों की निगरानी करना चाहेंगे, और प्रति-आईपी पते के योग (कम सीमा के साथ) भी।

ये चेक "सर्वर रहित" हो सकते हैं क्योंकि आप उन्हें अपने डेस्कटॉप पर चला सकते हैं। (यानी S3 सभी काम करता है, ये प्रक्रियाएँ बस वहाँ आपको आपके S3 बाल्टी के दुरुपयोग के लिए सचेत करती हैं ताकि आपको महीने के अंत में एक विशाल AWS बिल न मिले ।)


3
आदमी, मैं भूल गया कि लैम्ब्डा से पहले कितनी जटिल चीजें थीं।
रयान

10

स्वीकृत उत्तर में अधिक जानकारी जोड़ते हुए, आप एडब्ल्यूएस सिग्नेचर संस्करण 4 का उपयोग करके कोड के एक रनिंग संस्करण को देखने के लिए मेरे ब्लॉग का संदर्भ ले सकते हैं।

यहाँ संक्षेप में बताएंगे:

जैसे ही उपयोगकर्ता अपलोड की जाने वाली फ़ाइल का चयन करता है, निम्न कार्य करें: 1. आवश्यक सर्वर जनरेट करने के लिए सेवा शुरू करने के लिए वेब सर्वर पर कॉल करें

  1. इस सेवा में, अस्थायी क्रेडेंशियल प्राप्त करने के लिए AWS IAM सेवा को कॉल करें

  2. एक बार जब आपके पास क्रेडिट हो, तो एक बकेट पॉलिसी (बेस 64 एन्कोडेड स्ट्रिंग) बनाएं। फिर अंतिम हस्ताक्षर उत्पन्न करने के लिए अस्थायी गुप्त पहुंच कुंजी के साथ बाल्टी नीति पर हस्ताक्षर करें

  3. यूआई में आवश्यक पैरामीटर वापस भेजें

  4. एक बार यह प्राप्त हो जाने के बाद, एक HTML फॉर्म ऑब्जेक्ट बनाएं, आवश्यक पैरामेट्स सेट करें और इसे पोस्ट करें।

विस्तृत जानकारी के लिए, कृपया https://wordpress1763.wordpress.com/2016/10/03/browser-based-upload-aws-signature-version-4/ देखें।


5
मैंने एक पूरा दिन जावास्क्रिप्ट में यह जानने की कोशिश की, और यह उत्तर मुझे बताता है कि XMLhttprequest का उपयोग करके यह कैसे करना है। मुझे बहुत आश्चर्य है कि आप नीचे उतर गए। ओपी ने जावास्क्रिप्ट के लिए कहा और अनुशंसित उत्तरों में प्रपत्र प्राप्त किए। सुखद दुख। इस उत्तर के लिए धन्यवाद!
पॉल एस।

BTW सुपरगेंट में गंभीर CORS मुद्दे हैं, इसलिए xmlhttprequest को अभी ऐसा करने का एकमात्र उचित तरीका लगता है
पॉल एस

4

हस्ताक्षर बनाने के लिए, मुझे अपनी गुप्त कुंजी का उपयोग करना चाहिए। लेकिन सभी चीजें क्लाइंट साइड पर होती हैं, इसलिए, गुप्त कुंजी को आसानी से पृष्ठ स्रोत से प्रकट किया जा सकता है (भले ही मैं अपने स्रोतों को बाधित / एन्क्रिप्ट करता हूं)।

यह वह जगह है जहाँ आपको गलत समझा गया है। डिजिटल हस्ताक्षर का उपयोग करने का बहुत कारण है ताकि आप अपनी गुप्त कुंजी को प्रकट किए बिना किसी चीज़ को सही रूप में सत्यापित कर सकें। इस मामले में डिजिटल हस्ताक्षर का उपयोग उपयोगकर्ता को फॉर्म पोस्ट के लिए आपके द्वारा निर्धारित नीति को संशोधित करने से रोकने के लिए किया जाता है।

डिजिटल हस्ताक्षर जैसे कि यहां वेब के चारों ओर सुरक्षा के लिए उपयोग किया जाता है। यदि कोई (NSA?) वास्तव में उन्हें तोड़ने में सक्षम था, तो आपके S3 बाल्टी की तुलना में उनके पास बहुत बड़े लक्ष्य होंगे :)


2
लेकिन एक रोबोट असीमित फ़ाइलों को जल्दी से अपलोड करने का प्रयास कर सकता है। क्या मैं प्रति बाल्टी अधिकतम फ़ाइलों की नीति निर्धारित कर सकता हूं?
देजेल

3

मैंने जावास्क्रिप्ट ब्राउज़र से AWS S3 में फाइलें अपलोड करने और S3 बाल्टी में सभी फाइलों को सूचीबद्ध करने के लिए एक सरल कोड दिया है।

कदम:

  1. Create IdentityPoolId http://docs.aws.amazon.com/cognito/latest/developerguide/identity-pools.html बनाने का तरीका जानने के लिए

    1. गोटो एस 3 के कंसोल पेज और बाल्टी गुणों से कॉर्स कॉन्फ़िगरेशन खोलें और उस में एक्सएमएल कोड का पालन करें।

      <?xml version="1.0" encoding="UTF-8"?>
      <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
       <CORSRule>    
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>DELETE</AllowedMethod>
        <AllowedMethod>HEAD</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
       </CORSRule>
      </CORSConfiguration>
    2. निम्न कोड वाली HTML फ़ाइल बनाएँ, क्रेडेंशियल्स को बदलें, ब्राउज़र में फ़ाइल खोलें और आनंद लें।

      <script type="text/javascript">
       AWS.config.region = 'ap-north-1'; // Region
       AWS.config.credentials = new AWS.CognitoIdentityCredentials({
       IdentityPoolId: 'ap-north-1:*****-*****',
       });
       var bucket = new AWS.S3({
       params: {
       Bucket: 'MyBucket'
       }
       });
      
       var fileChooser = document.getElementById('file-chooser');
       var button = document.getElementById('upload-button');
       var results = document.getElementById('results');
      
       function upload() {
       var file = fileChooser.files[0];
       console.log(file.name);
      
       if (file) {
       results.innerHTML = '';
       var params = {
       Key: n + '.pdf',
       ContentType: file.type,
       Body: file
       };
       bucket.upload(params, function(err, data) {
       results.innerHTML = err ? 'ERROR!' : 'UPLOADED.';
       });
       } else {
       results.innerHTML = 'Nothing to upload.';
       }    }
      </script>
      <body>
       <input type="file" id="file-chooser" />
       <input type="button" onclick="upload()" value="Upload to S3">
       <div id="results"></div>
      </body>

2
क्या कोई भी मेरे S3 बाल्टी में फाइलें अपलोड करने के लिए मेरे "IdentityPoolId" का उपयोग नहीं कर पाएगा। यह समाधान किसी भी 3 पार्टी को सिर्फ मेरे "आइडेंटिटीपूलआईड" की नकल करने से रोक रहा है और बहुत सारी फाइलें मेरे S3 बकेट में अपलोड कर रहा है?
साहिल

1
stackoverflow.com/users/4535741/sahil आप अन्य डोमेन से डेटा को अपलोड करने से रोकने के लिए उपयुक्त कॉर्स सेटिंग करके S3 बाल्टी पर रोक सकते हैं। यहां तक ​​कि अगर कोई भी आपकी पहचान पूल आईडी तक पहुंच गया है तो वे आपकी s3 बाल्टी फ़ाइलों में हेरफेर नहीं कर सकते हैं।
नीलेश पवार

2

यदि आपके पास कोई सर्वर साइड कोड नहीं है, तो आप सुरक्षा क्लाइंट पक्ष पर अपने जावास्क्रिप्ट कोड तक पहुंच की सुरक्षा पर निर्भर करते हैं (यानी हर व्यक्ति जिसके पास कोड कुछ अपलोड कर सकता है)।

इसलिए, मैं आपको एक विशेष S3 बाल्टी बनाने की सिफारिश करूंगा, जो सार्वजनिक लेखन योग्य है (लेकिन पठनीय नहीं है), इसलिए आपको क्लाइंट पक्ष पर किसी भी हस्ताक्षरित घटकों की आवश्यकता नहीं है।

बाल्टी नाम (एक GUID उदा) दुर्भावनापूर्ण अपलोड के खिलाफ आपका एकमात्र बचाव होगा (लेकिन एक संभावित हमलावर डेटा को स्थानांतरित करने के लिए आपकी बाल्टी का उपयोग नहीं कर सकता है, क्योंकि यह केवल उसे लिखा गया है)


1

यहां बताया गया है कि आप नोड और सर्वर रहित का उपयोग करके एक नीति दस्तावेज़ कैसे बनाते हैं

"use strict";

const uniqid = require('uniqid');
const crypto = require('crypto');

class Token {

    /**
     * @param {Object} config SSM Parameter store JSON config
     */
    constructor(config) {

        // Ensure some required properties are set in the SSM configuration object
        this.constructor._validateConfig(config);

        this.region = config.region; // AWS region e.g. us-west-2
        this.bucket = config.bucket; // Bucket name only
        this.bucketAcl = config.bucketAcl; // Bucket access policy [private, public-read]
        this.accessKey = config.accessKey; // Access key
        this.secretKey = config.secretKey; // Access key secret

        // Create a really unique videoKey, with folder prefix
        this.key = uniqid() + uniqid.process();

        // The policy requires the date to be this format e.g. 20181109
        const date = new Date().toISOString();
        this.dateString = date.substr(0, 4) + date.substr(5, 2) + date.substr(8, 2);

        // The number of minutes the policy will need to be used by before it expires
        this.policyExpireMinutes = 15;

        // HMAC encryption algorithm used to encrypt everything in the request
        this.encryptionAlgorithm = 'sha256';

        // Client uses encryption algorithm key while making request to S3
        this.clientEncryptionAlgorithm = 'AWS4-HMAC-SHA256';
    }

    /**
     * Returns the parameters that FE will use to directly upload to s3
     *
     * @returns {Object}
     */
    getS3FormParameters() {
        const credentialPath = this._amazonCredentialPath();
        const policy = this._s3UploadPolicy(credentialPath);
        const policyBase64 = new Buffer(JSON.stringify(policy)).toString('base64');
        const signature = this._s3UploadSignature(policyBase64);

        return {
            'key': this.key,
            'acl': this.bucketAcl,
            'success_action_status': '201',
            'policy': policyBase64,
            'endpoint': "https://" + this.bucket + ".s3-accelerate.amazonaws.com",
            'x-amz-algorithm': this.clientEncryptionAlgorithm,
            'x-amz-credential': credentialPath,
            'x-amz-date': this.dateString + 'T000000Z',
            'x-amz-signature': signature
        }
    }

    /**
     * Ensure all required properties are set in SSM Parameter Store Config
     *
     * @param {Object} config
     * @private
     */
    static _validateConfig(config) {
        if (!config.hasOwnProperty('bucket')) {
            throw "'bucket' is required in SSM Parameter Store Config";
        }
        if (!config.hasOwnProperty('region')) {
            throw "'region' is required in SSM Parameter Store Config";
        }
        if (!config.hasOwnProperty('accessKey')) {
            throw "'accessKey' is required in SSM Parameter Store Config";
        }
        if (!config.hasOwnProperty('secretKey')) {
            throw "'secretKey' is required in SSM Parameter Store Config";
        }
    }

    /**
     * Create a special string called a credentials path used in constructing an upload policy
     *
     * @returns {String}
     * @private
     */
    _amazonCredentialPath() {
        return this.accessKey + '/' + this.dateString + '/' + this.region + '/s3/aws4_request';
    }

    /**
     * Create an upload policy
     *
     * @param {String} credentialPath
     *
     * @returns {{expiration: string, conditions: *[]}}
     * @private
     */
    _s3UploadPolicy(credentialPath) {
        return {
            expiration: this._getPolicyExpirationISODate(),
            conditions: [
                {bucket: this.bucket},
                {key: this.key},
                {acl: this.bucketAcl},
                {success_action_status: "201"},
                {'x-amz-algorithm': 'AWS4-HMAC-SHA256'},
                {'x-amz-credential': credentialPath},
                {'x-amz-date': this.dateString + 'T000000Z'}
            ],
        }
    }

    /**
     * ISO formatted date string of when the policy will expire
     *
     * @returns {String}
     * @private
     */
    _getPolicyExpirationISODate() {
        return new Date((new Date).getTime() + (this.policyExpireMinutes * 60 * 1000)).toISOString();
    }

    /**
     * HMAC encode a string by a given key
     *
     * @param {String} key
     * @param {String} string
     *
     * @returns {String}
     * @private
     */
    _encryptHmac(key, string) {
        const hmac = crypto.createHmac(
            this.encryptionAlgorithm, key
        );
        hmac.end(string);

        return hmac.read();
    }

    /**
     * Create an upload signature from provided params
     * https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html#signing-request-intro
     *
     * @param policyBase64
     *
     * @returns {String}
     * @private
     */
    _s3UploadSignature(policyBase64) {
        const dateKey = this._encryptHmac('AWS4' + this.secretKey, this.dateString);
        const dateRegionKey = this._encryptHmac(dateKey, this.region);
        const dateRegionServiceKey = this._encryptHmac(dateRegionKey, 's3');
        const signingKey = this._encryptHmac(dateRegionServiceKey, 'aws4_request');

        return this._encryptHmac(signingKey, policyBase64).toString('hex');
    }
}

module.exports = Token;

उपयोग की गई कॉन्फ़िगरेशन ऑब्जेक्ट SSM पैरामीटर स्टोर में संग्रहीत है और इस तरह दिखता है

{
    "bucket": "my-bucket-name",
    "region": "us-west-2",
    "bucketAcl": "private",
    "accessKey": "MY_ACCESS_KEY",
    "secretKey": "MY_SECRET_ACCESS_KEY",
}

0

यदि आप तृतीय पक्ष सेवा का उपयोग करने के इच्छुक हैं, तोमाण 0.com इस एकीकरण का समर्थन करता है। SSL0 सेवा एक्सचेंज AWS अस्थायी सत्र टोकन के लिए 3rd पार्टी SSO सेवा प्रमाणीकरण की अनुमति देता है।

देखें: https://github.com/auth0-samples/auth0-s3-sample/
और ओड़िआ प्रलेखन।


1
जैसा कि मैंने समझा - अब हमारे पास इसके लिए कॉग्निटो है?
विटाली ज़डनेविच
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.