# Import the interface required by the Script snap. from com.snaplogic.scripting.language import ScriptHook import java.util from sys import version from random import randint from base64 import b64encode from time import time from urllib import quote_plus from hashlib import sha1 import hmac #----------------------------------------------------------------------------- # Oooh, super handy link in case you want to know what the hell some of the # above imports are bringing in: # # https://docs.python.org/release/2.6.6/modindex.html #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # getValue() abstracts the work of finding a value in a dictionary and # assigning a default value if not found #----------------------------------------------------------------------------- def getValue(inDict, inKey, defaultValue=""): try: outVal = inDict[inKey] except: outVal = defaultValue return outVal #----------------------------------------------------------------------------- # makeNonce() generates a random 32-character string #----------------------------------------------------------------------------- def makeNonce(): set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" size = 32 newKey = "" max = len(set) - 1 for x in range(0, len(set)): i = randint(0, max) newKey += set[i] return newKey[:size] class TransformScript(ScriptHook): def __init__(self, input, output, error, log): self.input = input self.output = output self.error = error self.log = log # The "execute()" method is called once when the pipeline is started # and allowed to process its inputs or just send data to its outputs. def execute(self): self.log.info("Executing Transform script") while self.input.hasNext(): try: # Read the next document, wrap it in a map and write out the wrapper in_doc = self.input.next() #---------------------------------------------------------------------- # For our purposes, there's really only going to be ONE document passed # into this script, which is all the values provided in the preceding # Mapper snap. So, we'll just assign all those values to local # variables; the REAL meat of this script will happen after we exit # this while loop #---------------------------------------------------------------------- accountId = getValue(in_doc, "accountId") baseUrl = getValue(in_doc, "baseUrl") scriptId = getValue(in_doc, "scriptId") deployId = getValue(in_doc, "deployId") oauthVersion = getValue(in_doc, "oauthVersion") tokenId = getValue(in_doc, "tokenId") tokenSecret = getValue(in_doc, "tokenSecret") consumerKey = getValue(in_doc, "consumerKey") consumerSecret = getValue(in_doc, "consumerSecret") restletType = getValue(in_doc, "restletType") pageSize = getValue(in_doc, "pageSize") startPage = getValue(in_doc, "startPage") except Exception as e: errWrapper = { 'errMsg' : str(e.args) } self.log.error("Error in python script") self.error.write(errWrapper) #--------------------------------------------------------------------------- # Generate a timestamp and nonce. The nonce comes from the function above, # while the timestamp should in THEORY be the # of seconds since the epoch #--------------------------------------------------------------------------- timeStamp = int(time()) nonce = makeNonce() #--------------------------------------------------------------------------- # The data variable will be a string of values that will be encoded and # encrypted to become the oauth signature value #--------------------------------------------------------------------------- data = "deploy=%s" % (deployId) data += "&oauth_consumer_key=%s" % (consumerKey) data += "&oauth_nonce=%s" % (nonce) data += "&oauth_signature_method=HMAC-SHA1" data += "&oauth_timestamp=%d" % (timeStamp) data += "&oauth_token=%s" % (tokenId) data += "&oauth_version=%s" % (oauthVersion) data += "&page=%s" % (startPage) data += "&pageSize=%s" % (pageSize) data += "&script=%s" % (scriptId) data += "&type=%s" % (restletType) #--------------------------------------------------------------------------- # quote_plus is a built-in library function that will uuencode a string so # that it can be passed safely via a url. # # Then, hmac does the encryption of the string as a whole. #--------------------------------------------------------------------------- encodedData = quote_plus(data) completeData = "GET&" + quote_plus(baseUrl) + "&" + encodedData hmacData = hmac.new("%s&%s" % (consumerSecret, tokenSecret), completeData, sha1) #--------------------------------------------------------------------------- # Because apparently you can never be TOO secure, next we'll do base64 # encoding on the encrypted value, and then uuencode THAT as well #--------------------------------------------------------------------------- base64data = b64encode(hmacData.digest().rstrip('\n')) oauthSignature = quote_plus(base64data) #--------------------------------------------------------------------------- # The oauthStr is the final combined value that will be passed as the # "Authorization" value in the REST header call for the actual RESTlet. #--------------------------------------------------------------------------- oauthStr = "OAuth oauth_signature=\"" + oauthSignature + "\"," oauthStr += "oauth_version=\"%s\"," % (oauthVersion) oauthStr += "oauth_nonce=\"%s\"," % (nonce) oauthStr += "oauth_signature_method=\"HMAC-SHA1\"," oauthStr += "oauth_consumer_key=\"" + consumerKey + "\"," oauthStr += "oauth_token=\"" + tokenId + "\"," oauthStr += "oauth_timestamp=\"%d\"," % (timeStamp) oauthStr += "realm=\"%s\"" % (accountId) #--------------------------------------------------------------------------- # Last bit: take all the stuff from above and build into a JSON-type output # record that will be sent as output from the Script snap. #--------------------------------------------------------------------------- wrapper = java.util.HashMap() wrapper["timeStamp"] = timeStamp wrapper["completeData"] = completeData wrapper["oauthString"] = oauthStr wrapper["accountId"] = accountId wrapper["baseUrl"] = baseUrl wrapper["scriptId"] = scriptId wrapper["deployId"] = deployId wrapper["oauthVersion"] = oauthVersion wrapper["tokenId"] = tokenId wrapper["tokenSecret"] = tokenSecret wrapper["consumerKey"] = consumerKey wrapper["consumerSecret"] = consumerSecret wrapper["restletType"] = restletType wrapper["pageSize"] = pageSize wrapper["startPage"] = startPage wrapper["pythonVersion"] = version self.output.write(in_doc, wrapper) self.log.info("Finished executing the Transform script") # The Script Snap will look for a ScriptHook object in the "hook" # variable. The snap will then call the hook's "execute" method. hook = TransformScript(input, output, error, log)