1- var VERSION = 0.2 ;
2-
1+ var VERSION = 0.3 ;
32var util = require ( 'util' ) ;
3+ var assert = require ( 'assert' ) ;
44var aws = require ( 'aws-sdk' ) ;
55var s3 = new aws . S3 ( { apiVersion : '2006-03-01' } ) ;
66var http = require ( 'https' ) ;
@@ -9,27 +9,111 @@ var crypto = require('crypto');
99
1010// replace below with your credentials in the form key:secret
1111// to create your key go to https://scanii.com/account/settings/keys
12- var SCANII_CREDS = 'KEY:SECRET' ;
12+ var SCANII_CREDS = 'CHANGE' ;
13+ // replace with the URL of your callback lambda function
14+ var CALLBACK_URL = 'ME' ;
15+
16+
17+ onFindings = function ( bucket , key , result , context ) {
18+ console . log ( 'RESULT:' , internalId ( bucket , key ) , 'has findings' , result . findings ) ;
19+ var pending = true ;
20+
21+ // sample code that delete objects with findings from S3:
22+ var req = s3 . deleteObject ( { Bucket : bucket , Key : key } ) ;
23+ req . on ( 'success' , function ( response ) {
24+ console . log ( console . log ( 'file' , internalId ( bucket , key ) , 'deleted' ) ) ;
25+ context . succeed ( util . format ( 'callback for file %s completed successful' , result . id ) ) ;
26+ pending = false ;
27+
28+ } ) . on ( 'error' , function ( response ) {
29+ console . log ( console . log ( 'error while deleting' , internalId ( bucket , key ) ) ) ;
30+ context . fail ( response ) ;
31+ pending = false ;
32+ } ) ;
33+ req . send ( ) ;
34+ var waitWhilePending = function ( ) {
35+ if ( pending ) {
36+ console . log ( 'waiting' ) ;
37+ setTimeout ( waitWhilePending , 100 ) ;
38+ }
39+ } ;
40+ setTimeout ( waitWhilePending , 100 ) ;
41+
42+ } ;
43+
44+ onNoFindings = function ( bucket , key , result , context ) {
45+ console . log ( 'RESULT:' , internalId ( bucket , key ) , 'has no findings' ) ;
46+ context . succeed ( util . format ( 'callback for file %s completed successful' , result . id ) ) ;
47+
48+ } ;
49+
1350
14- // Do not edit below this line
51+ //------------------------------- Do not edit below this line ----------------------------------------------
52+
53+ // if the credentials are passed via an env variable we honor it:
54+ if ( process . env . SCANII_CREDS !== undefined ) {
55+ console . log ( 'loading credentials from environment variable' ) ;
56+ SCANII_CREDS = process . env . SCANII_CREDS ;
57+ }
1558
1659const API_ENDPOINT = '/v2.1/files/' ;
1760
18- console . log ( 'Loading function v' , VERSION ) ;
61+ console . log ( 'loading function v' , VERSION ) ;
1962
2063var KEY = SCANII_CREDS . split ( ':' ) [ 0 ] ;
2164var SECRET = SCANII_CREDS . split ( ':' ) [ 1 ] ;
65+ console . log ( 'using key' , KEY ) ;
66+
67+ var internalId = function ( bucket , key ) {
68+ return util . format ( 's3://%s/%s' , bucket , key ) ;
69+ } ;
70+
71+ var generateSignature = function ( bucket , key ) {
72+ return crypto . createHmac ( 'sha1' , SECRET ) . update ( internalId ( bucket , key ) ) . digest ( 'hex' ) ;
73+ } ;
74+
75+ /**
76+ * Handles HTTP result callback
77+ */
78+ var handleCallback = function ( event , context ) {
79+ console . log ( 'handling callback event' ) ;
80+
81+ var r = event ;
82+ //console.log('response:', JSON.stringify(r, null, 2));
83+ console . log ( "metadata:" , r . metadata ) ;
84+
85+ // callback sanity checks
86+ assert . ok ( r . id !== undefined , "no id provided" ) ;
87+ assert . ok ( r . metadata !== undefined , "no metadata supplied" ) ;
88+ assert . ok ( r . metadata . bucket !== undefined , "no bucket supplied in metadata" ) ;
89+ assert . ok ( r . metadata . key !== undefined , "no key supplied in metadata" ) ;
90+ assert . ok ( r . metadata . signature !== undefined , "no signature supplied in metadata" ) ;
91+
92+ // now asserting bucket/keys were not tampered with:
93+ assert . ok ( r . metadata . signature == generateSignature ( r . metadata . bucket , r . metadata . key ) , "invalid signature" ) ;
94+ console . log ( 'signature check passed for signature' , r . metadata . signature ) ;
95+
96+ if ( r . findings !== undefined ) {
97+ if ( r . findings . length > 0 ) {
98+ onFindings ( r . metadata . bucket , r . metadata . key , r , context ) ;
99+ } else {
100+ onNoFindings ( r . metadata . bucket , r . metadata . key , r , context ) ;
101+ }
102+ }
22103
23- var internalId = function ( bucket , key ) {
24- return util . format ( 'processing s3://%s/%s' , bucket , key ) ;
25104} ;
26105
27- exports . handler = function ( event , context ) {
28- console . log ( 'Received event:' , JSON . stringify ( event , null , 2 ) ) ;
106+
107+ /**
108+ * Handles S3 event and submits content for processing
109+ */
110+ var handleS3Event = function ( event , context ) {
111+ console . log ( 'handling S3 event' ) ;
29112
30113 // Get the object from the event and show its content type
31114 var bucket = event . Records [ 0 ] . s3 . bucket . name ;
32- var key = event . Records [ 0 ] . s3 . object . key ;
115+ // see https://forums.aws.amazon.com/thread.jspa?threadID=215813
116+ var key = Object . keys ( qs . decode ( event . Records [ 0 ] . s3 . object . key ) ) [ 0 ] ;
33117
34118 console . log ( 'processing ' + internalId ( bucket , key ) ) ;
35119
@@ -40,20 +124,21 @@ exports.handler = function (event, context) {
40124 Expires : 3600 // 1 hour
41125 } ) ;
42126 console . log ( 'created signed url' , url ) ;
43- console . log ( 'submitting content for processing' ) ;
44127
128+
129+ console . log ( 'submitting content for processing' ) ;
45130 // signing request
46- var signature = crypto . createHmac ( 'sha1' , SECRET ) . update ( internalId ( bucket , key ) ) . digest ( 'hex' ) ;
131+ var signature = generateSignature ( bucket , key ) ;
47132 console . log ( 'using signature ' + signature ) ;
48133
49134 var payload = qs . stringify ( {
50135 location : url ,
51- 'metadata[hmac]' : signature ,
52- 'metadata[id]' : internalId ( bucket , key )
136+ callback : CALLBACK_URL ,
137+ 'metadata[signature]' : signature ,
138+ 'metadata[bucket]' : bucket ,
139+ 'metadata[key]' : key
53140 } ) ;
54141
55- console . log ( payload ) ;
56-
57142 var options = {
58143 auth : SCANII_CREDS ,
59144 port : 443 ,
@@ -63,27 +148,41 @@ exports.handler = function (event, context) {
63148 headers : {
64149 'Content-Type' : 'application/x-www-form-urlencoded' ,
65150 'Content-Length' : payload . length ,
66- 'User-Agent' : 'scanii-mu /v' + VERSION
151+ 'User-Agent' : 'scanii-lambda /v' + VERSION
67152 }
68153 } ;
69-
154+ console . log ( payload ) ;
70155 // calling scanii API v2.1 (http://docs.scanii.com/v2.1/resources.html):
71156 var req = http . request ( options , function ( res ) {
72- console . log ( "statusCode: " , res . statusCode ) ;
73157 console . log ( "headers: " , res . headers ) ;
74158
75159 res . on ( 'data' , function ( data ) {
76160 var serviceResponse = JSON . parse ( data ) ;
77- console . log ( 'file id:' , serviceResponse . id ) ;
78- context . succeed ( 'OK - id ' + serviceResponse . id ) ;
161+ if ( res . statusCode == 202 ) {
162+ console . log ( 'file id:' , serviceResponse . id ) ;
163+ context . succeed ( serviceResponse . id ) ;
164+ } else {
165+ console . log ( serviceResponse ) ;
166+ context . fail ( util . format ( "Error: invalid response from server, message [%s] and http code: %d" , serviceResponse . body , res . statusCode ) ) ;
167+ }
168+ } ) ;
169+ res . on ( 'error' , function ( error ) {
170+ context . fail ( error ) ;
79171 } ) ;
80172 } ) ;
81173
82174 req . write ( payload ) ;
83175 req . end ( ) ;
84176
85- req . on ( 'error' , function ( error ) {
86- console . log ( error ) ;
87- context . fail ( error ) ;
88- } ) ;
89177} ;
178+
179+ exports . handler = function ( event , context ) {
180+ console . log ( 'received event:' , JSON . stringify ( event , null , 2 ) ) ;
181+ if ( event . Records !== undefined ) {
182+ handleS3Event ( event , context ) ;
183+ } else {
184+ handleCallback ( event , context ) ;
185+ }
186+ } ;
187+
188+ exports . generateSignature = generateSignature ;
0 commit comments