diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 842189a..fbca910 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -40,7 +40,7 @@ jobs: if: matrix.os == 'ubuntu-latest' run: | sudo apt-get install libkrb5-dev - pip install kerberos requests + pip install -r devel.txt - name: Build & start services run: | @@ -72,10 +72,6 @@ jobs: make verify-web-login klist - - name: Install coverage tools - run: | - pip install codecov - - name: Verify tcms-api can communicate via username/password run: | cat > ~/.tcms.conf << _EOF_ diff --git a/.travis.yml b/.travis.yml index a0d5441..1e023d1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ env: - MAKE=build install: - - pip install codecov pylint flake8 twine kerberos requests + - pip install -r devel.txt script: - make $MAKE diff --git a/MANIFEST.in b/MANIFEST.in index 0c73842..645a28c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1 @@ -include README.rst LICENSE +include README.rst LICENSE requirements.txt diff --git a/README.rst b/README.rst index 6642545..cafb0d4 100644 --- a/README.rst +++ b/README.rst @@ -40,6 +40,12 @@ INSTALLATION pip install tcms-api +**WARNING:** on Windows you need to install MIT Kerberos and make sure +``C:\Program Files\MIT\Kerberos\bin`` is included in ``%PATH%`` - +this is usually the case when you install and restart! It must be +a 64bit installation, see +`MIT Kerberos for Windows 4.1 `_ + CHANGELOG --------- diff --git a/appveyor.yml b/appveyor.yml index 5fb945d..3d8dc7d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,6 +9,12 @@ environment: - MAKE: build install: + # install MIT Kerberos for Windows + - SET PATH=%PATH%;"C:\\Program Files\\MIT\\Kerberos\\bin"' + - "curl -fsS -o kfw-4.1-amd64.msi https://web.mit.edu/kerberos/dist/kfw/4.1/kfw-4.1-amd64.msi" + # NOTE: always exit 0 b/c the installer needs restart but we're forcing it not to + - "msiexec /i kfw-4.1-amd64.msi /quiet /qn /norestart & exit 0" + # Prepend Python to the PATH of this build (this cannot be done from inside # the powershell script as it would require to restart the parent CMD process). # cygwin64\bin contains all commands used by 'make build' @@ -16,7 +22,7 @@ install: - "python --version" - "python -m pip install --disable-pip-version-check --user --upgrade pip wheel" - - "python -m pip install codecov pylint flake8 twine winkerberos requests" + - "python -m pip install -r devel.txt" build: off @@ -28,5 +34,6 @@ artifacts: test_script: - 'sed -i "s|-p \$(which python)||" tests/check-build' - 'sed -i "s|bin/activate|Scripts/activate|" tests/check-build' - - 'sed -i "s|pip install kerberos||" tests/check-build' + - 'sed -i "s|--no-binary :all: gssapi|--only-binary :all: gssapi|" tests/check-build' + - 'sed -i "s|pip install gssapi||" tests/check-build' - "make %MAKE%" diff --git a/devel.txt b/devel.txt new file mode 100644 index 0000000..ed2e2bb --- /dev/null +++ b/devel.txt @@ -0,0 +1,6 @@ +-r requirements.txt + +codecov +flake8 +pylint +twine diff --git a/docs/source/conf.py b/docs/source/conf.py index 240fbc3..56e3862 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -20,7 +20,7 @@ # generate documentation from Python sources subprocess.run(['make', '-C', '../', 'apidoc'], check=True) -autodoc_mock_imports = ['kerberos'] +autodoc_mock_imports = ['gssapi'] # -- General configuration ------------------------------------------------ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a647d3a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +gssapi +requests diff --git a/setup.py b/setup.py index 699c964..2ee59f0 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,5 @@ #!/usr/bin/env python import os -import sys from setuptools import setup @@ -11,12 +10,22 @@ def get_version(): ).replace('__version__=', '').strip().strip("'").strip('"') +def get_install_requires(path): + requires = [] + + with open(path, 'r') as file: + for line in file: + if line.startswith('-r '): + continue + requires.append(line.strip()) + return requires + + with open("README.rst") as readme: LONG_DESCRIPTION = readme.read() setup(name='tcms-api', - # always update version/release in docs/conf.py version=get_version(), packages=['tcms_api'], description='Python API for Kiwi', @@ -27,10 +36,7 @@ def get_version(): license='LGPLv2+', url='https://github.com/kiwitcms/tcms-api', python_requires='>=3.6', - install_requires=[ - 'requests', - 'winkerberos' if sys.platform.startswith("win") else 'kerberos', - ], + install_requires=get_install_requires('requirements.txt'), classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Console', diff --git a/tcms_api/xmlrpc.py b/tcms_api/xmlrpc.py index 0fdc660..212a6a9 100644 --- a/tcms_api/xmlrpc.py +++ b/tcms_api/xmlrpc.py @@ -1,20 +1,17 @@ # pylint: disable=too-few-public-methods -import sys import urllib.parse +from base64 import b64encode from http import HTTPStatus from http.client import HTTPSConnection from xmlrpc.client import SafeTransport, Transport, ServerProxy +import gssapi import requests from tcms_api.version import __version__ -if sys.platform.startswith("win"): - import winkerberos as kerberos # pylint: disable=import-error -else: - import kerberos # pylint: disable=import-error VERBOSE = 0 @@ -45,9 +42,8 @@ class SafeCookieTransport(SafeTransport, CookieTransport): scheme = 'https' -# Taken from FreeIPA source freeipa-1.2.1/ipa-python/krbtransport.py class KerbTransport(SafeCookieTransport): - """Handles Kerberos Negotiation authentication to an XML-RPC server.""" + """Handles GSSAPI Negotiation (SPNEGO) authentication.""" def get_host_info(self, host): host, extra_headers, x509 = Transport.get_host_info(self, host) @@ -56,12 +52,12 @@ def get_host_info(self, host): hostinfo = host.split(':') service = "HTTP@" + hostinfo[0] - _result, context = kerberos.authGSSClientInit(service) - kerberos.authGSSClientStep(context, "") + service_name = gssapi.Name(service, gssapi.NameType.hostbased_service) + context = gssapi.SecurityContext(usage="initiate", name=service_name) + token = context.step() extra_headers = [ - ("Authorization", "Negotiate %s" % - kerberos.authGSSClientResponse(context)) + ("Authorization", "Negotiate %s" % b64encode(token).decode()) ] return host, extra_headers, x509 diff --git a/tests/check-build b/tests/check-build index 8709eed..d0be74a 100755 --- a/tests/check-build +++ b/tests/check-build @@ -46,7 +46,8 @@ echo "..... Trying to install the new tarball inside a virtualenv" virtualenv -q -p $(which python) .venv/test-tarball source .venv/test-tarball/bin/activate pip install --upgrade setuptools pip -pip install --no-binary :all: -f dist/ tcms-api +pip install --no-binary :all: gssapi +pip install --no-binary :all: dist/tcms-api*.tar.gz pip freeze | grep tcms-api deactivate rm -rf .venv/ @@ -55,8 +56,8 @@ echo "..... Trying to install the new wheel inside a virtualenv" virtualenv -q -p $(which python) .venv/test-wheel source .venv/test-wheel/bin/activate pip install --upgrade setuptools pip -pip install kerberos -pip install --only-binary :all: -f dist/ tcms_api +pip install gssapi +pip install --only-binary :all: dist/tcms_api*.whl pip freeze | grep tcms-api deactivate rm -rf .venv/