123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- # -*- coding: utf-8 -*-
- import time
- import requests
- import json
- import logging
- import threading
- from .exceptions import ClientError
- from .utils import to_unixtime
- from .compat import to_unicode
- logger = logging.getLogger(__name__)
- class Credentials(object):
- def __init__(self, access_key_id="", access_key_secret="", security_token=""):
- self.access_key_id = access_key_id
- self.access_key_secret = access_key_secret
- self.security_token = security_token
- def get_access_key_id(self):
- return self.access_key_id
- def get_access_key_secret(self):
- return self.access_key_secret
- def get_security_token(self):
- return self.security_token
- DEFAULT_ECS_SESSION_TOKEN_DURATION_SECONDS = 3600 * 6
- DEFAULT_ECS_SESSION_EXPIRED_FACTOR = 0.85
- class EcsRamRoleCredential(Credentials):
- def __init__(self,
- access_key_id,
- access_key_secret,
- security_token,
- expiration,
- duration,
- expired_factor=None):
- self.access_key_id = access_key_id
- self.access_key_secret = access_key_secret
- self.security_token = security_token
- self.expiration = expiration
- self.duration = duration
- self.expired_factor = expired_factor or DEFAULT_ECS_SESSION_EXPIRED_FACTOR
- def get_access_key_id(self):
- return self.access_key_id
- def get_access_key_secret(self):
- return self.access_key_secret
- def get_security_token(self):
- return self.security_token
- def will_soon_expire(self):
- now = int(time.time())
- return self.duration * (1.0 - self.expired_factor) > self.expiration - now
- class CredentialsProvider(object):
- def get_credentials(self):
- return
- class StaticCredentialsProvider(CredentialsProvider):
- def __init__(self, access_key_id="", access_key_secret="", security_token=""):
- self.credentials = Credentials(access_key_id, access_key_secret, security_token)
- def get_credentials(self):
- return self.credentials
- class EcsRamRoleCredentialsProvider(CredentialsProvider):
- def __init__(self, auth_host, max_retries=3, timeout=10):
- self.fetcher = EcsRamRoleCredentialsFetcher(auth_host)
- self.max_retries = max_retries
- self.timeout = timeout
- self.credentials = None
- self.__lock = threading.Lock()
- def get_credentials(self):
- if self.credentials is None or self.credentials.will_soon_expire():
- with self.__lock:
- if self.credentials is None or self.credentials.will_soon_expire():
- try:
- self.credentials = self.fetcher.fetch(self.max_retries, self.timeout)
- except Exception as e:
- logger.error("Exception: {0}".format(e))
- if self.credentials is None:
- raise
- return self.credentials
- class EcsRamRoleCredentialsFetcher(object):
- def __init__(self, auth_host):
- self.auth_host = auth_host
- def fetch(self, retry_times=3, timeout=10):
- for i in range(0, retry_times):
- try:
- response = requests.get(self.auth_host, timeout=timeout)
- if response.status_code != 200:
- raise ClientError(
- "Failed to fetch credentials url, http code:{0}, msg:{1}".format(response.status_code,
- response.text))
- dic = json.loads(to_unicode(response.content))
- code = dic.get('Code')
- access_key_id = dic.get('AccessKeyId')
- access_key_secret = dic.get('AccessKeySecret')
- security_token = dic.get('SecurityToken')
- expiration_date = dic.get('Expiration')
- last_updated_date = dic.get('LastUpdated')
- if code != "Success":
- raise ClientError("Get credentials from ECS metadata service error, code: {0}".format(code))
- expiration_stamp = to_unixtime(expiration_date, "%Y-%m-%dT%H:%M:%SZ")
- duration = DEFAULT_ECS_SESSION_TOKEN_DURATION_SECONDS
- if last_updated_date is not None:
- last_updated_stamp = to_unixtime(last_updated_date, "%Y-%m-%dT%H:%M:%SZ")
- duration = expiration_stamp - last_updated_stamp
- return EcsRamRoleCredential(access_key_id, access_key_secret, security_token, expiration_stamp,
- duration, DEFAULT_ECS_SESSION_EXPIRED_FACTOR)
- except Exception as e:
- if i == retry_times - 1:
- logger.error("Exception: {0}".format(e))
- raise ClientError("Failed to get credentials from ECS metadata service. {0}".format(e))
|