From 8020427f0fdcef0e898a33239732a503d998ee94 Mon Sep 17 00:00:00 2001 From: Marius Wirtz Date: Mon, 20 May 2019 21:30:08 +0200 Subject: [PATCH] Enable platform independency - Fail-safe import of (windows-only) dependecy requests_negotiate_sspi - Optional dependency to requests_negotiate_sspi in setup.py only in windows os Fixes #127 --- TM1py/Services/RESTService.py | 49 +++++++++++++++++++++++------------ Tests/config.ini | 4 +-- setup.py | 8 ++++-- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/TM1py/Services/RESTService.py b/TM1py/Services/RESTService.py index 7d17dad1..774d0120 100644 --- a/TM1py/Services/RESTService.py +++ b/TM1py/Services/RESTService.py @@ -1,11 +1,17 @@ # -*- coding: utf-8 -*- import functools import sys +import warnings from base64 import b64encode, b64decode import requests from requests.adapters import HTTPAdapter -from requests_negotiate_sspi import HttpNegotiateAuth + +# SSO not supported for Linux +try: + from requests_negotiate_sspi import HttpNegotiateAuth +except ImportError: + warnings.warn("requests_negotiate_sspi failed to import. SSO will not work", ImportWarning) from TM1py.Exceptions import TM1pyException @@ -274,24 +280,33 @@ def _build_authorization_token(user, password, namespace=None, gateway=None, **k """ Build the Authorization Header for CAM and Native Security """ if namespace: - if gateway: - response = requests.get(gateway, auth=HttpNegotiateAuth()) - if not response.status_code == 200: - raise RuntimeError( - "Failed to authenticate through CAM. Expected status_code 200, received status_code: " - + str(response.status_code)) - elif 'cam_passport' not in response.cookies: - raise RuntimeError( - "Failed to authenticate through CAM. HTTP response does not contain 'cam_passport' cookie") - else: - token = 'CAMPassport ' + response.cookies['cam_passport'] + return RESTService._build_authorization_token_cam(user, password, namespace, gateway) + else: + return RESTService._build_authorization_token_basic(user, password) + + @staticmethod + def _build_authorization_token_cam(user=None, password=None, namespace=None, gateway=None): + if gateway: + if not HttpNegotiateAuth: + raise RuntimeError( + "SSO failed due to missing dependency requests_negotiate_sspi.HttpNegotiateAuth. " + "SSO only supported for Windows") + response = requests.get(gateway, auth=HttpNegotiateAuth()) + if not response.status_code == 200: + raise RuntimeError( + "Failed to authenticate through CAM. Expected status_code 200, received status_code: " + + str(response.status_code)) + elif 'cam_passport' not in response.cookies: + raise RuntimeError( + "Failed to authenticate through CAM. HTTP response does not contain 'cam_passport' cookie") else: - token = 'CAMNamespace ' + b64encode( - str.encode("{}:{}:{}".format(user, password, namespace))).decode("ascii") + return 'CAMPassport ' + response.cookies['cam_passport'] else: - token = 'Basic ' + b64encode( - str.encode("{}:{}".format(user, password))).decode("ascii") - return token + return 'CAMNamespace ' + b64encode(str.encode("{}:{}:{}".format(user, password, namespace))).decode("ascii") + + @staticmethod + def _build_authorization_token_basic(user, password): + return 'Basic ' + b64encode(str.encode("{}:{}".format(user, password))).decode("ascii") @staticmethod def disable_http_warnings(): diff --git a/Tests/config.ini b/Tests/config.ini index 9c6f13f1..8e2184a4 100644 --- a/Tests/config.ini +++ b/Tests/config.ini @@ -1,11 +1,11 @@ -[tm1srv02] +[tm1srv01] address=10.77.19.60 port=12354 user=Admin password=apple ssl=True -[tm1srv01] +[tm1srv02] address=10.77.19.60 port=9699 user=Admin diff --git a/setup.py b/setup.py index 5128cee8..91287479 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup -SCHEDULE_VERSION = '1.3.0' +SCHEDULE_VERSION = '1.3.1' SCHEDULE_DOWNLOAD_URL = ( 'https://github.com/Cubewise-code/TM1py/tarball/' + SCHEDULE_VERSION ) @@ -35,6 +35,10 @@ 'Programming Language :: Python :: 3.6', 'Natural Language :: English', ], - install_requires=['requests', 'pandas', 'pytz', 'requests_negotiate_sspi'], + install_requires=[ + 'requests', + 'pandas', + 'pytz', + 'requests_negotiate_sspi;platform_system=="Windows"'], python_requires='>=3.5', )