import sys, os, datetime, hashlib, hmac from StringIO import StringIO import gzip import urllib import urllib2 import json def get_filters_2(**kwargs): filter_stack = [] canonical_querystring = "" url_encoding = kwargs.get("url_encoding") sources = kwargs.get("sources") if sources: source_string = "SourceId=" + ",".join(sources) filter_stack.append(source_string) devices = kwargs.get("devices") if devices: device_string = "Device=" + ",".join(devices) filter_stack.append(device_string) priorities = kwargs.get("priorities") if priorities: priority_string = "Priority=" + ",".join(str(item) for item in priorities) filter_stack.append(priority_string) types = kwargs.get("types") if types: type_string = ("Type=" + ",".join(str(item) for item in types)) filter_stack.append(type_string) time_from = kwargs.get("start") if time_from: time_from_string = "StartTimestamp=" + str(time_from) filter_stack.append(time_from_string) time_to = kwargs.get("end") if time_to: time_to_string = "EndTimestamp=" + str(time_to) filter_stack.append(time_to_string) duration = kwargs.get("duration") if duration: duration_string = "MinimumDuration=" + str(duration) filter_stack.append(duration_string) if filter_stack: if url_encoding: canonical_querystring += "Filter=" for i, j in enumerate(filter_stack): if i == len(filter_stack)-1 and url_encoding == True: canonical_querystring += urllib.quote(j, "") elif i == len(filter_stack)-1: canonical_querystring += j elif url_encoding == True: canonical_querystring += urllib.quote(j + "&", "") else: canonical_querystring += (j + "&") return canonical_querystring def get_filters(**kwargs): #Build filter string, filters are passed as key word arguments into the function #Check if any of the filters have been passed means we need to add Filter=. #Each filter is then converted using the urllib_parse. canonical_querystring = "" sources = kwargs.get("sources") devices = kwargs.get("devices") priorities = kwargs.get("priorities") types = kwargs.get("types") time_from = kwargs.get("start") time_to = kwargs.get("end") duration = kwargs.get("duration") url_encoding = kwargs.get("url_encoding") filter_list = [sources, devices, priorities, types, time_from, time_to, duration] if any(filter_list): canonical_querystring = "Filter=" if sources: source_string = ("SourceId=" + ",".join(sources)) if url_encoding == True: canonical_querystring += urllib.quote(source_string + "&","") else: canonical_querystring += source_string + "&" if devices: device_string = ("Device=" + ",".join(devices)) if url_encoding == True: canonical_querystring += urllib.quote(device_string + "&","") else: canonical_querystring += device_string +"&" if priorities: priority_string = ("Priority=" + ",".join(str(item) for item in priorities)) if url_encoding == True: canonical_querystring += urllib.quote(priority_string + "&", "") else: canonical_querystring += priority_string +"&" if types: type_string = ("Type=" + ",".join(str(item) for item in types)) if url_encoding == True: canonical_querystring += urllib.quote(type_string + "&","") else: canonical_querystring += type_string +"&" if time_from: if url_encoding == True: canonical_querystring += urllib.quote("StartTimestamp=" + str(time_from) + "&","") else: canonical_querystring += "StartTimestamp=" + str(time_from) +"&" if time_to: if url_encoding == True: canonical_querystring += urllib.quote("EndTimestamp=" + str(time_to) + "&","") else: canonical_querystring += "EndTimestamp=" + str(time_to) +"&" if duration: if url_encoding == True: canonical_querystring += urllib.quote("MinimumDuration=" + str(duration) + "&","") else: canonical_querystring += "MinimumDuration=" + str(duration) +"&" system.perspective.print("filtered string = " + canonical_querystring ) canonical_querystring = canonical_querystring.rstrip("&") return canonical_querystring def get_response(response): if response.info().get('Content-Encoding') == 'gzip': buf = StringIO(response.read()) f = gzip.GzipFile(fileobj=buf) data = f.read() return (response.getcode(), data) else: buf = StringIO(response.read()) return(response.getcode(), buf.read()) def build_url(credentials, **kwargs): # ************* REQUEST VALUES ************* method = 'GET' service = 'lambda' # This is a lookup in secrets to a return the function url for the lambda that needs called. # This allows beta and prod to be dynamically retrived. whid = kwargs.get("fc") region = kwargs.get("region") API_ID, STAGE, ACC_ID, FUNC_URL = AWS.secrets_manager.get_secret(str(whid), 'scada/api/endpoint') api_id = FUNC_URL host = "%s.%s-url.%s.on.aws" % (api_id, service, region) endpoint = "https://%s" % (host) # Key derivation functions. See: # http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python def sign(key, msg): return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest() def getSignatureKey(key, dateStamp, regionName, serviceName): kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp) kRegion = sign(kDate, regionName) kService = sign(kRegion, serviceName) kSigning = sign(kService, 'aws4_request') return kSigning # Read AWS access key from env. variables or configuration file. Best practice is NOT # to embed credentials in code. # access_key = os.environ.get('AWS_ACCESS_KEY_ID') # access_key= 'ASIATVSVCYSV2JJJMDPP' # secret_key = os.environ.get('AWS_SECRET_ACCESS_KEY') # secret_key= 'Hc0G/0eACBlgplGSBnfsB98Y6DPqwpvyb4nc1Rvs' # session_token = os.environ["AWS_SESSION_TOKEN"] # session_token= 'IQoJb3JpZ2luX2VjEJr//////////wEaCWV1LXdlc3QtMSJHMEUCIQCbrPQoj4OM0SXIo6QtcNAblnplgXfvSYIcA+k8xkXmZwIgN1Pi7Nyc66T8p0HkZSMmuW8pu1qPEVJii41YgYCuiBYqngIIo///////////ARAAGgwyNTI1MDc3Njc5NzkiDKGV69tLNcKNVcoeryryARkU2Lmnj0aa+ilLOrg35FIb81jvmj6bpPR3+5zJ3Wna+vOBgz6cqphyn28+Q8Ryw/lzM6gM0vWH+gV26CuQZtKd1U4ETo9eL9QuluLBqLnZYfT5q+F9hzJy3OQQl0c3VvwcaCjOPrMdbvWnJGEoEZTKe7Xm5v3ok3huJDgKLEIVlE6Z4c2kKNy/N/JfbxB5a33A2eaE9YaGj1V0cQgUFCCkn9uDq8W4TzOPZ3NgKAyj8RoBR6KAC8gEtWXFEwwZR3ZMwYIXryEepcU7HQSHpp66JAFm/X5+HNxRe7WUwTETAveYMNi5ssFzl3rneKh9+U37MPW58psGOp0B11BghSma0KZHgCfXqdsgfGyD7/sBEyYE9wdnzmi8fOpel5EDQoUoYilRSXod2E9wlaXj3h8S+dtBJjGVqsIbHEIrW7WKOEYELxoW4VSDw5hDjZaUuZ5fA3z59c4CEeAz3v5EA6NN6+ulEb7/4pbWF8s3fezNk9T73NpmKnjaMFukcBX8DofesZGJFpfGij2Sx4hQ3qlmG91uac8kMw==' access_key = credentials["AccessKey"] secret_key = credentials["SecretKey"] session_token = credentials["SessionKey"] if access_key is None or secret_key is None: system.perspective.print('No access key is available.') sys.exit() # Create a date for headers and the credential string t = datetime.datetime.utcnow() amz_date = t.strftime('%Y%m%dT%H%M%SZ') # Format date as YYYYMMDD'T'HHMMSS'Z' datestamp = t.strftime('%Y%m%d') # Date w/o time, used in credential scope system.perspective.print("creating header") system.perspective.print("datestamp = " + str(datestamp) + " region = " + str(region) + "service = " + str(service)) # ************* TASK 1: CREATE A CANONICAL REQUEST ************* # http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html # Because almost all information is being passed in the query string, # the order of these steps is slightly different than examples that # use an authorization header. # Step 1: Define the verb (GET, POST, etc.)--already done. # Step 2: Create canonical URI--the part of the URI from domain to query # string (use '/' if no path) fc = kwargs.get("fc") canonical_uri = "/history/%s" % (fc) # Step 3: Create the canonical headers and signed headers. Header names # must be trimmed and lowercase, and sorted in code point order from # low to high. Note trailing \n in canonical_headers. # signed_headers is the list of headers that are being included # as part of the signing process. For requests that use query strings, # only "host" is included in the signed headers. canonical_headers = 'host:' + host + '\n' signed_headers = 'host' # Match the algorithm to the hashing algorithm you use, either SHA-1 or # SHA-256 (recommended) algorithm = 'AWS4-HMAC-SHA256' credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request' # Step 4: Create the canonical query string. In this example, request # parameters are in the query string. Query string values must # be URL-encoded (space=%20). The parameters must be sorted by name. #canonical_querystring = 'Action=CreateUser&UserName=NewUser&Version=2010-05-08' #canonical_querystring = 'NextToken=' + urllib.parse.quote("1669217267.5230844/PLC09/T00049",'') + '&PageSize=50' #canonical_querystring = 'PageSize=50&PreviousToken=' + urllib.parse.quote('1669217267.5824845/PLC09/T00099','') canonical_querystring = "" #Build filter string, filters are passed as key word arguments int the function #Check if any of the filters have been passed means we need to add Filter=. #Each filter is then converted using the urllib_parse. #Including client id for timestream api. client_id = kwargs.get("client_id") if client_id: canonical_querystring += 'ClientId=' + client_id + '&' PAGE_SIZE = "200" filters= kwargs.get("filters","") if filters != "": canonical_querystring += filters + "&" next_token = kwargs.get("next_token") previous_token = kwargs.get("previous_token") if next_token != None: canonical_querystring += 'NextToken=' + urllib.quote(next_token,'') + '&' system.perspective.print("created string " + canonical_querystring) if previous_token != None: canonical_querystring += 'PreviousToken=' + urllib.quote(previous_token,'') + '&' else: canonical_querystring += 'X-Amz-Algorithm=AWS4-HMAC-SHA256' canonical_querystring += '&X-Amz-Credential=' + urllib.quote_plus(access_key + '/' + credential_scope) canonical_querystring += '&X-Amz-Date=' + amz_date #canonical_querystring += '&X-Amz-Expires=30' canonical_querystring += "&X-Amz-Security-Token=" + urllib.quote_plus(session_token) canonical_querystring += '&X-Amz-SignedHeaders=' + signed_headers # Step 5: Create payload hash. For GET requests, the payload is an # empty string (""). payload_hash = hashlib.sha256(('').encode('utf-8')).hexdigest() # Step 6: Combine elements to create canonical request canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash # ************* TASK 2: CREATE THE STRING TO SIGN************* string_to_sign = algorithm + '\n' + amz_date + '\n' + credential_scope + '\n' + hashlib.sha256(canonical_request.encode('utf-8')).hexdigest() # ************* TASK 3: CALCULATE THE SIGNATURE ************* # Create the signing key signing_key = getSignatureKey(secret_key, datestamp, region, service) # Sign the string_to_sign using the signing_key signature = hmac.new(signing_key, (string_to_sign).encode("utf-8"), hashlib.sha256).hexdigest() # ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST ************* # The auth information can be either in a query string # value or in a header named Authorization. This code shows how to put # everything into a query string. canonical_querystring += '&X-Amz-Signature=' + signature # ************* SEND THE REQUEST ************* # The 'host' header is added automatically by the Python 'request' lib. But it # must exist as a header in the request. request_url = endpoint + canonical_uri + "?" + canonical_querystring system.perspective.print('\nBEGIN REQUEST++++++++++++++++++++++++++++++++++++') system.perspective.print('Request URL = ' + request_url) # r = requests.get(request_url) request = urllib2.Request(request_url) request.add_header('Accept-encoding', 'gzip') try: response = urllib2.urlopen(request) except urllib2.HTTPError as e: return(e.code, None) except urllib2.URLError as e: return(e.reason, None) return get_response(response)