def _handle_single_request(self, endpoint, request, read_timeout, connect_timeout, signer): http_response = self._make_http_response(endpoint, request, read_timeout, connect_timeout, signer) params = copy.deepcopy(request.get_query_params()) params.pop('AccessKeyId', None) logger.debug('Request received. Product:%s Endpoint:%s Params: %s', request.get_product(), endpoint, params) # Do the actual network thing try: status, headers, body = http_response.get_response_object() except IOError as e: exception = ClientException(error_code.SDK_HTTP_ERROR, compat.ensure_string('%s' % e)) msg = "HttpError occurred. Host:%s SDK-Version:%s ClientException:%s" % ( endpoint, aliyunsdkcore.__version__, exception) logger.error(compat.ensure_string(msg)) return None, None, None, exception exception = self._get_server_exception(status, body, endpoint, request.string_to_sign) return status, headers, body, exception
def _get_server_exception(self, http_status, response_body, endpoint, string_to_sign): request_id = None try: body_obj = json.loads(response_body.decode('utf-8')) request_id = body_obj.get('RequestId') except (ValueError, TypeError, AttributeError): # in case the response body is not a json string, return the raw # data instead logger.warning( 'Failed to parse response as json format. Response:%s', response_body) if http_status < codes.OK or http_status >= codes.MULTIPLE_CHOICES: server_error_code, server_error_message = self._parse_error_info_from_response_body( response_body.decode('utf-8')) if http_status == codes.BAD_REQUEST and server_error_code == 'SignatureDoesNotMatch': if string_to_sign == server_error_message.split(':')[1]: server_error_code = 'InvalidAccessKeySecret' server_error_message = 'The AccessKeySecret is incorrect. ' \ 'Please check your AccessKeyId and AccessKeySecret.' exception = ServerException(server_error_code, server_error_message, http_status=http_status, request_id=request_id) msg = "ServerException occurred. Host:%s SDK-Version:%s ServerException:%s" % ( endpoint, aliyunsdkcore.__version__, exception) logger.error(compat.ensure_string(msg)) return exception
def _refresh_session_ak_and_sk(self): request = CommonRequest(product="Sts", version='2015-04-01', action_name='AssumeRole') request.set_method('POST') request.set_protocol_type('https') request.add_query_param('RoleArn', self._credential.role_arn) request.add_query_param('RoleSessionName', self._credential.session_role_name) request.add_query_param('DurationSeconds', self._SESSION_PERIOD) request.set_accept_format('JSON') access_key_credential = AccessKeyCredential(self._credential.sts_access_key_id, self._credential.sts_access_key_secret) signer = AccessKeySigner(access_key_credential) status, headers, body, exception = self._doAction(request, signer) if status == 200: response = json.loads(body.decode('utf-8')) session_ak = response.get("Credentials").get("AccessKeyId") session_sk = response.get("Credentials").get("AccessKeySecret") token = response.get("Credentials").get("SecurityToken") self._session_credential = session_ak, session_sk, token self._last_update_time = int(time.time()) else: code = error_code.SDK_GET_SESSION_CREDENTIAL_FAILED message = "refresh session token failed, server return: " + ensure_string(body) http_status = status raise exceptions.ServerException(code, message, http_status)
def do_action_with_exception(self, request: RpcRequest): request.set_accept_format('JSON') path = request.path_pattern if hasattr( request, 'path_pattern') else '/api/acs/openapi' if self._endpoint: endpoint = self._endpoint elif request.endpoint: endpoint = request.endpoint else: endpoint = self._resolve_endpoint(request) request.add_query_param('Product', request.get_product()) request.add_query_param('RegionId', self.get_region_id()) request.add_query_param('Action', request.get_action_name()) request.add_query_param('Version', request.get_version()) request._params.update(self.query_params) sign_params = dict(request._params) query, sign_str = get_signed_url(sign_params, self.get_access_key(), self.get_access_secret(), request.get_accept_format(), request.get_method(), request.get_body_params(), self.query_params) request.string_to_sign = sign_str endpoint += path response = HttpResponse( endpoint, query, request.get_method(), request.get_signed_header(self.get_region_id(), self.get_access_key(), self.get_access_secret()), request.get_protocol_type(), request.get_content(), self._port) if self._read_timeout: response._timeout = response.__read_timeout = self._read_timeout if self._connect_timeout: response.__connect_timeout = self._connect_timeout try: status, headers, body = response.get_response_object() except IOError as e: exception = ClientException(error_code.SDK_HTTP_ERROR, compat.ensure_string('%s' % e)) return None, None, None, exception exception = self.get_server_exception(status, body) if exception: raise exception return body
def get_sign_string(source, access_secret): key = load_der_private_key( b64_decode_bytes(ensure_bytes(access_secret)), password=None, backend=default_backend() ) signed_bytes = key.sign( ensure_bytes(source), padding.PKCS1v15(), hashes.SHA256() ) signed_base64 = b64_encode_bytes(signed_bytes) signature = ensure_string(signed_base64).replace('\n', '') return signature
def _parse_error_info_from_response_body(response_body): error_code_to_return = error_code.SDK_UNKNOWN_SERVER_ERROR # TODO handle if response_body is too big error_message_to_return = compat.ensure_string("ServerResponseBody: %s" % (response_body,)) try: body_obj = json.loads(response_body) if 'Code' in body_obj: error_code_to_return = body_obj['Code'] if 'Message' in body_obj: error_message_to_return = body_obj['Message'] except ValueError: # failed to parse body as json format logger.warning('Failed to parse response as json format. Response:%s', response_body) return error_code_to_return, error_message_to_return
def get_sign_string(source, access_secret): if platform.system() != "Windows": from Crypto.Signature import PKCS1_v1_5 from Crypto.Hash import SHA256 from Crypto.PublicKey import RSA key = RSA.importKey(b64_decode_bytes(ensure_bytes(access_secret))) h = SHA256.new(ensure_bytes(source)) signer = PKCS1_v1_5.new(key) signed_bytes = signer.sign(h) signed_base64 = b64_encode_bytes(signed_bytes) signature = ensure_string(signed_base64).replace('\n', '') return signature else: message = "auth type [publicKeyId] is disabled in Windows " \ "because 'pycrypto' is not supported, we will resolve " \ "this soon" raise exceptions.ClientException(error_code.SDK_NOT_SUPPORT, message)
def get_md5_base64_str(content): m = hashlib.md5() content_bytes = ensure_bytes(content) m.update(ensure_bytes(content_bytes)) return ensure_string(b64_encode_bytes(m.digest()).strip())
def get_sign_string(source, secret): source = ensure_bytes(source) secret = ensure_bytes(secret) h = hmac.new(secret, source, hashlib.sha1) signature = ensure_string(b64_encode_bytes(h.digest()).strip()) return signature
def md5_sum(content): content_bytes = ensure_bytes(content) md5_bytes = hashlib.md5(content_bytes).digest() return ensure_string(base64.standard_b64encode(md5_bytes))
def get_md5_base64_str(content): return ensure_string(b64_encode_bytes(_get_md5(content)).strip())