require'aws-sigv4'require'json'require'net/http'require'aws-sdk-lambda'# Idlc::SERVICES object is loaded from core lib# default regionENV['AWS_REGION']='us-east-1'unlessENV['AWS_REGION']moduleIdlcclassAWSLambdaProxyincludeHelpersdeffetch(request)client=Aws::Lambda::Client.new()region=ENV['AWS_REGION']backend_services=Idlc::SERVICES[region]request[:function]="#{request[:service]}-"+backend_services[request[:service]]['stage']+"-#{request[:lambda]}"request[:httpMethod]=request[:method]retries=0max_retries=5sleep_time=5exp_backoff=2result=nilloopdobeginresp=client.invoke({function_name: "service-lambda-proxy",invocation_type: "RequestResponse",log_type: "None",payload: request.to_json,})result=JSON.parse(JSON.parse(JSON.parse(resp.payload.string)['Payload'])['body'])breakrescueException=>ebreakifretries>=max_retriesretries+=1msg("RequestFailed: #{e} - Waiting #{sleep_time}s then retrying... (#{retries} of #{max_retries})")sleepsleep_timesleep_time*=exp_backoff# use an exponential backoff when retrying requestsendendresultendendclassAWSRestClientincludeHelpersdefinitialize(credentials={access_key_id: ENV['AWS_ACCESS_KEY_ID'],secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],session_token: ENV['AWS_SESSION_TOKEN']},region=ENV['AWS_REGION'])@service_name='execute-api'@credentials=credentials@region=region@backend_services=Idlc::SERVICES[region]enddeffetch(request)request=JSON.parse(request)endpoint='https://'+@backend_services[request['service']]['endpoint']+'/'+@backend_services[request['service']]['stage']body=''body=request['body'].to_jsonifrequest['body']retries=0max_retries=5sleep_time=5exp_backoff=2result=nilloopdobeginresp=send_signed_request(request['method'],"#{endpoint.strip}#{request['path']}",body)result=JSON.parse(resp.body)message="status: #{resp.code}, response: #{result}"raisemessageunlessresp.code=='200'breakrescueException=>ebreakifretries>=max_retriesretries+=1msg("RequestFailed: #{e} - Waiting #{sleep_time}s then retrying... (#{retries} of #{max_retries})")sleepsleep_timesleep_time*=exp_backoff# use an exponential backoff when retrying requestsendend# if request has 'outfile' param, write response body to fileto_file(result,request['outfile'])ifrequest['outfile']# return response body objresultenddefto_file(obj,filename)File.open(filename,'w')do|f|f.write(obj.to_json)endendprivatedefsend_signed_request(method,url,payload)uri=URI.parse(url)https=Net::HTTP.new(uri.host,uri.port)https.use_ssl=truesignature=sigv4_signature(method,url,payload)path=uri.pathpath=path+'?'+uri.queryifuri.queryrequest=http_request(method,path,signature,payload)response=https.request(request)enddefset_headers(request,signature)request.add_field'content-type','application/json'request.add_field'host',signature.headers['host']request.add_field'x-amz-date',signature.headers['x-amz-date']request.add_field'x-amz-security-token',signature.headers['x-amz-security-token']unless(signature.headers['x-amz-security-token'].nil?)request.add_field'x-amz-content-sha256',signature.headers['x-amz-content-sha256']request.add_field'authorization',signature.headers['authorization']enddefhttp_request(method,path,signature,payload)casemethod.downcasewhen'put'request=Net::HTTP::Put.new(path)when'post'request=Net::HTTP::Post.new(path)when'get'request=Net::HTTP::Get.new(path)when'delete'request=Net::HTTP::Delete.new(path)elserequest=Net::HTTP::Put.new(path)endset_headers(request,signature)request.body=payloadrequestenddefsignerAws::Sigv4::Signer.new(service: @service_name,region: @region,access_key_id: @credentials[:access_key_id],secret_access_key: @credentials[:secret_access_key],session_token: @credentials[:session_token])enddefsigv4_signature(method,url,payload)signer.sign_request(http_method: method,url: url,headers: {'content-type'=>'application/json'},body: payload)endendend