<commit_before># -*- coding: utf-8 -*-
'''
Connection library for AWS

.. versionadded:: Lithium

This is a base library used by a number of AWS services.

:depends: requests
'''
from __future__ import absolute_import

# Import Python libs
import sys
import time
import binascii
import datetime
import hashlib
import hmac
import logging

# Import Salt libs
import salt.utils.xmlutil as xml
from salt._compat import ElementTree as ET

# Import 3rd-party libs
import requests
# pylint: disable=import-error,redefined-builtin,no-name-in-module
from salt.ext.six.moves import map, range, zip
from salt.ext.six.moves.urllib.parse import urlencode, urlparse
# pylint: enable=import-error,redefined-builtin,no-name-in-module

LOG = logging.getLogger(__name__)
DEFAULT_LOCATION = 'us-east-1'
DEFAULT_AWS_API_VERSION = '2014-10-01'
AWS_RETRY_CODES = [
    'RequestLimitExceeded',
    'InsufficientInstanceCapacity',
    'InternalError',
    'Unavailable',
    'InsufficientAddressCapacity',
    'InsufficientReservedInstanceCapacity',
]

IROLE_CODE = 'use-instance-role-credentials'
__AccessKeyId__ = ''
__SecretAccessKey__ = ''
__Token__ = ''
__Expiration__ = ''

def creds(provider):
    '''
    Return the credentials for AWS signing.  This could be just the id and key
    specified in the provider configuration, or if the id or key is set to the
    literal string 'use-instance-role-credentials' creds will pull the instance
    role credentials from the meta data, cache them, and provide them instead.
    '''
    # Declare globals
    global __AccessKeyId__, __SecretAccessKey__, __Token__, __Expiration__

    # if id or key is 'use-instance-role-credentials', pull them from meta-data
    ## if needed
    if provider['id'] == IROLE_CODE or provider['key'] == IROLE_CODE:
        # Check to see if we have cache credentials that are still good
        if __Expiration__ != '':
            timenow = datetime.datetime.utcnow()
            timestamp = timenow.strftime('%Y-%m-%dT%H:%M:%SZ')
            if timestamp < __Expiration__:
                # Current timestamp less than expiration fo cached credentials
                return __AccessKeyId__, __SecretAccessKey__, __Token__
        # We don't have any cached credentials, or they are expired, get them
        # TODO: Wrap this with a try and handle exceptions gracefully
        result = requests.get(
            "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
        )
        result.raise_for_status()
        role = result.text
        # TODO: Wrap this with a try and handle exceptions gracefully
        result = requests.get(
            "http://169.254.169.254/latest/meta-data/iam/security-credentials/{0}".format(role)
        )
        result.raise_for_status()
        data = result.json()
        __AccessKeyId__ = data['AccessKeyId']
        __SecretAccessKey__ = data['SecretAccessKey']
        __Token__ = data['Token']
        __Expiration__ = data['Expiration']
        return __AccessKeyId__, __SecretAccessKey__, __Token__
    else:
        return provider['id'], provider['key'], ''


def sig2(method, endpoint, params, provider, aws_api_version):
    '''
    Sign a query against AWS services using Signature Version 2 Signing
    Process. This is documented at:

    http://docs.aws.amazon.com/general/latest/gr/signature-version-2.html
    '''
    # Declare globals
    global __AccessKeyId__, __SecretAccessKey__, __Token__

    timenow = datetime.datetime.utcnow()
    timestamp = timenow.strftime('%Y-%m-%dT%H:%M:%SZ')

    # Retrieve access credentials from meta-data, or use provided
    access_key_id, secret_access_key, token = creds(prov_dict)

    params_with_headers = params.copy()
    params_with_headers['AWSAccessKeyId'] = access_key_id
    params_with_headers['SignatureVersion'] = '2'
    params_with_headers['SignatureMethod'] = 'HmacSHA256'
    params_with_headers['Timestamp'] = '{0}'.format(timestamp)
    params_with_headers['Version'] = aws_api_version
    keys = sorted(params_with_headers.keys())
    values = list(list(map(params_with_headers.get, keys)))
    querystring = urlencode(list(zip(keys, values)))

    canonical = '{0}\n{1}\n/\n{2}'.format(
        method.encode('utf-8'),
        endpoint.encode('utf-8'),
        querystring.encode('utf-8'),
    )

    hashed = hmac.new(secret_access_key, canonical, hashlib.sha256)
    sig = binascii.b2a_base64(hashed.digest())
    params_with_headers['Signature'] = sig.strip()

    # Add in security token if we have one
    if token != '':
        params_with_headers['SecurityToken'] = token

    return params_with_headers


def sig4(method, endpoint, params, prov_dict, aws_api_version, location,
         product='ec2', uri='/', requesturl=None):
    '''
    Sign a query against AWS services using Signature Version 4 Signing
    Process. This is documented at:

    http://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
    http://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
    http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
    '''
    # Declare globals
    global __AccessKeyId__, __SecretAccessKey__, __Token__

    timenow = datetime.datetime.utcnow()
    timestamp = timenow.strftime('%Y-%m-%dT%H:%M:%SZ')

    # Retrieve access credentials from meta-data, or use provided
    access_key_id, secret_access_key, token = creds(prov_dict)

    params_with_headers = params.copy()<commit_msg>global not needed in sig2 and sig4<commit_after># -*- coding: utf-8 -*-
'''
Connection library for AWS

.. versionadded:: Lithium

This is a base library used by a number of AWS services.

:depends: requests
'''
from __future__ import absolute_import

# Import Python libs
import sys
import time
import binascii
import datetime
import hashlib
import hmac
import logging

# Import Salt libs
import salt.utils.xmlutil as xml
from salt._compat import ElementTree as ET

# Import 3rd-party libs
import requests
# pylint: disable=import-error,redefined-builtin,no-name-in-module
from salt.ext.six.moves import map, range, zip
from salt.ext.six.moves.urllib.parse import urlencode, urlparse
# pylint: enable=import-error,redefined-builtin,no-name-in-module

LOG = logging.getLogger(__name__)
DEFAULT_LOCATION = 'us-east-1'
DEFAULT_AWS_API_VERSION = '2014-10-01'
AWS_RETRY_CODES = [
    'RequestLimitExceeded',
    'InsufficientInstanceCapacity',
    'InternalError',
    'Unavailable',
    'InsufficientAddressCapacity',
    'InsufficientReservedInstanceCapacity',
]

IROLE_CODE = 'use-instance-role-credentials'
__AccessKeyId__ = ''
__SecretAccessKey__ = ''
__Token__ = ''
__Expiration__ = ''

def creds(provider):
    '''
    Return the credentials for AWS signing.  This could be just the id and key
    specified in the provider configuration, or if the id or key is set to the
    literal string 'use-instance-role-credentials' creds will pull the instance
    role credentials from the meta data, cache them, and provide them instead.
    '''
    # Declare globals
    global __AccessKeyId__, __SecretAccessKey__, __Token__, __Expiration__

    # if id or key is 'use-instance-role-credentials', pull them from meta-data
    ## if needed
    if provider['id'] == IROLE_CODE or provider['key'] == IROLE_CODE:
        # Check to see if we have cache credentials that are still good
        if __Expiration__ != '':
            timenow = datetime.datetime.utcnow()
            timestamp = timenow.strftime('%Y-%m-%dT%H:%M:%SZ')
            if timestamp < __Expiration__:
                # Current timestamp less than expiration fo cached credentials
                return __AccessKeyId__, __SecretAccessKey__, __Token__
        # We don't have any cached credentials, or they are expired, get them
        # TODO: Wrap this with a try and handle exceptions gracefully
        result = requests.get(
            "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
        )
        result.raise_for_status()
        role = result.text
        # TODO: Wrap this with a try and handle exceptions gracefully
        result = requests.get(
            "http://169.254.169.254/latest/meta-data/iam/security-credentials/{0}".format(role)
        )
        result.raise_for_status()
        data = result.json()
        __AccessKeyId__ = data['AccessKeyId']
        __SecretAccessKey__ = data['SecretAccessKey']
        __Token__ = data['Token']
        __Expiration__ = data['Expiration']
        return __AccessKeyId__, __SecretAccessKey__, __Token__
    else:
        return provider['id'], provider['key'], ''


def sig2(method, endpoint, params, provider, aws_api_version):
    '''
    Sign a query against AWS services using Signature Version 2 Signing
    Process. This is documented at:

    http://docs.aws.amazon.com/general/latest/gr/signature-version-2.html
    '''
    timenow = datetime.datetime.utcnow()
    timestamp = timenow.strftime('%Y-%m-%dT%H:%M:%SZ')

    # Retrieve access credentials from meta-data, or use provided
    access_key_id, secret_access_key, token = creds(prov_dict)

    params_with_headers = params.copy()
    params_with_headers['AWSAccessKeyId'] = access_key_id
    params_with_headers['SignatureVersion'] = '2'
    params_with_headers['SignatureMethod'] = 'HmacSHA256'
    params_with_headers['Timestamp'] = '{0}'.format(timestamp)
    params_with_headers['Version'] = aws_api_version
    keys = sorted(params_with_headers.keys())
    values = list(list(map(params_with_headers.get, keys)))
    querystring = urlencode(list(zip(keys, values)))

    canonical = '{0}\n{1}\n/\n{2}'.format(
        method.encode('utf-8'),
        endpoint.encode('utf-8'),
        querystring.encode('utf-8'),
    )

    hashed = hmac.new(secret_access_key, canonical, hashlib.sha256)
    sig = binascii.b2a_base64(hashed.digest())
    params_with_headers['Signature'] = sig.strip()

    # Add in security token if we have one
    if token != '':
        params_with_headers['SecurityToken'] = token

    return params_with_headers


def sig4(method, endpoint, params, prov_dict, aws_api_version, location,
         product='ec2', uri='/', requesturl=None):
    '''
    Sign a query against AWS services using Signature Version 4 Signing
    Process. This is documented at:

    http://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
    http://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
    http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
    '''
    timenow = datetime.datetime.utcnow()
    timestamp = timenow.strftime('%Y-%m-%dT%H:%M:%SZ')

    # Retrieve access credentials from meta-data, or use provided
    access_key_id, secret_access_key, token = creds(prov_dict)

    params_with_headers = params.copy()
{'fraction_non_alphanumeric': 0.10841919613849438, 'fraction_numerical': 0.011695906432748537, 'mean_word_length': 3.4835622138992925, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '185379', 'n_tokens_mistral': 3343, 'n_tokens_neox': 3220, 'n_words': 813}