diff --git a/freeipa.spec.in b/freeipa.spec.in index 521c9fd7f..fdca43a24 100755 --- a/freeipa.spec.in +++ b/freeipa.spec.in @@ -337,7 +337,6 @@ BuildRequires: keyutils BuildRequires: python3-augeas BuildRequires: python3-cffi BuildRequires: python3-cryptography >= 1.6 -BuildRequires: python3-custodia >= 0.3.1 BuildRequires: python3-dateutil BuildRequires: python3-dbus BuildRequires: python3-dns >= 1.15 @@ -506,7 +505,6 @@ Requires: %{name}-common = %{version}-%{release} Requires(pre): python3-ldap >= %{python_ldap_version} Requires: python3-augeas Requires: augeas-libs >= %{augeas_version} -Requires: python3-custodia >= 0.3.1 Requires: python3-dbus Requires: python3-dns >= 1.15 Requires: python3-gssapi >= 1.2.0 @@ -540,7 +538,6 @@ BuildArch: noarch Requires: %{name}-client-common = %{version}-%{release} Requires: httpd >= %{httpd_version} Requires: systemd-units >= %{systemd_version} -Requires: custodia >= 0.3.1 %if 0%{?rhel} >= 8 && ! 0%{?eln} Requires: system-logos-ipa >= 80.4 %endif diff --git a/ipaserver/custodia/__about__.py b/ipaserver/custodia/__about__.py deleted file mode 100644 index bef10e21a..000000000 --- a/ipaserver/custodia/__about__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (C) 2017 Custodia Project Contributors - see LICENSE file - -__all__ = [ - '__title__', '__summary__', '__uri__', '__version__', '__version_info__', - '__author__', '__email__', '__license__', '__copyright__', -] - -__title__ = 'custodia' -__summary__ = 'A service to manage, retrieve and store secrets.' -__uri__ = 'https://github.com/latchset/custodia' - -__version_info__ = (0, 6, 0) -__version__ = '.'.join(str(v) for v in __version_info__) - -__author__ = 'Custodia project Contributors' -__email__ = 'simo@redhat.com' - -__license__ = 'GPLv3+' -__copyright__ = 'Copyright 2015-2017 {0}'.format(__author__) diff --git a/ipaserver/custodia/compat.py b/ipaserver/custodia/compat.py deleted file mode 100644 index 7a6041dae..000000000 --- a/ipaserver/custodia/compat.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (C) 2015 Custodia Project Contributors - see LICENSE file -"""Python 2/3 compatibility -""" -# pylint: disable=no-name-in-module,import-error -from __future__ import absolute_import - -import six - - -if six.PY2: - # use https://pypi.python.org/pypi/configparser/ on Python 2 - from backports import configparser - from urllib import quote as url_escape - from urllib import quote_plus, unquote - from urlparse import parse_qs, urlparse -else: - import configparser - from urllib.parse import quote as url_escape - from urllib.parse import parse_qs, quote_plus, unquote, urlparse - - -__all__ = ( - 'configparser', - 'parse_qs', 'quote_plus', 'unquote', 'url_escape', 'urlparse' -) diff --git a/ipaserver/custodia/httpd/authenticators.py b/ipaserver/custodia/httpd/authenticators.py index f0ae14685..a679066a9 100644 --- a/ipaserver/custodia/httpd/authenticators.py +++ b/ipaserver/custodia/httpd/authenticators.py @@ -1,11 +1,7 @@ # Copyright (C) 2015 Custodia Project Contributors - see LICENSE file from __future__ import absolute_import -import os - -from cryptography.hazmat.primitives import constant_time - -from custodia import log +from ipaserver.custodia import log from ipaserver.custodia.plugin import HTTPAuthenticator, PluginOption @@ -55,80 +51,3 @@ class SimpleHeaderAuth(HTTPAuthenticator): request['client_id'], value) request['remote_user'] = value return True - - -class SimpleAuthKeys(HTTPAuthenticator): - id_header = PluginOption(str, 'CUSTODIA_AUTH_ID', "auth id header name") - key_header = PluginOption(str, 'CUSTODIA_AUTH_KEY', "auth key header name") - store = PluginOption('store', None, None) - store_namespace = PluginOption(str, 'custodiaSAK', "") - - def _db_key(self, name): - return os.path.join(self.store_namespace, name) - - def handle(self, request): - name = request['headers'].get(self.id_header, None) - key = request['headers'].get(self.key_header, None) - if name is None and key is None: - self.logger.debug('Ignoring request no relevant headers provided') - return None - - validated = False - try: - val = self.store.get(self._db_key(name)) - if val is None: - raise ValueError("No such ID") - if constant_time.bytes_eq(val.encode('utf-8'), - key.encode('utf-8')): - validated = True - except Exception: # pylint: disable=broad-except - self.audit_svc_access(log.AUDIT_SVC_AUTH_FAIL, - request['client_id'], name) - return False - - if validated: - self.audit_svc_access(log.AUDIT_SVC_AUTH_PASS, - request['client_id'], name) - request['remote_user'] = name - return True - - self.audit_svc_access(log.AUDIT_SVC_AUTH_FAIL, - request['client_id'], name) - return False - - -class SimpleClientCertAuth(HTTPAuthenticator): - header = PluginOption(str, 'CUSTODIA_CERT_AUTH', "header name") - - def handle(self, request): - cert_auth = request['headers'].get(self.header, "false").lower() - client_cert = request['client_cert'] # {} or None - if not client_cert or cert_auth not in {'1', 'yes', 'true', 'on'}: - self.logger.debug('Ignoring request no relevant header or cert' - ' provided') - return None - - subject = client_cert.get('subject', {}) - dn = [] - name = None - # TODO: check SAN first - for rdn in subject: - for key, value in rdn: - dn.append('{}="{}"'.format(key, value.replace('"', r'\"'))) - if key == 'commonName': - name = value - break - - dn = ', '.join(dn) - self.logger.debug('Client cert subject: {}, serial: {}'.format( - dn, client_cert.get('serialNumber'))) - - if name: - self.audit_svc_access(log.AUDIT_SVC_AUTH_PASS, - request['client_id'], name) - request['remote_user'] = name - return True - - self.audit_svc_access(log.AUDIT_SVC_AUTH_FAIL, - request['client_id'], dn) - return False diff --git a/ipaserver/custodia/httpd/authorizers.py b/ipaserver/custodia/httpd/authorizers.py index 64638163e..0061904cb 100644 --- a/ipaserver/custodia/httpd/authorizers.py +++ b/ipaserver/custodia/httpd/authorizers.py @@ -3,8 +3,8 @@ from __future__ import absolute_import import os -from custodia import log -from ipaserver.custodia.plugin import HTTPAuthorizer, PluginOption +from ipaserver.custodia import log +from ipaserver.custodia.plugin import HTTPAuthorizer class SimplePathAuthz(HTTPAuthorizer): @@ -46,35 +46,3 @@ class SimplePathAuthz(HTTPAuthorizer): self.logger.debug('No path in %s matched %s', self.paths, reqpath) return None - - -class UserNameSpace(HTTPAuthorizer): - path = PluginOption(str, '/', 'User namespace path') - store = PluginOption('store', None, None) - - def handle(self, request): - # Only check if we are in the right (sub)path - path = request.get('path', '/') - if not path.startswith(self.path): - self.logger.debug('%s is not contained in %s', path, self.path) - return None - - name = request.get('remote_user', None) - if name is None: - # UserNameSpace requires a user ... - self.audit_svc_access(log.AUDIT_SVC_AUTHZ_FAIL, - request['client_id'], path) - return False - - # pylint: disable=no-member - namespace = self.path.rstrip('/') + '/' + name + '/' - if not path.startswith(namespace): - # Not in the namespace - self.audit_svc_access(log.AUDIT_SVC_AUTHZ_FAIL, - request['client_id'], path) - return False - - request['default_namespace'] = name - self.audit_svc_access(log.AUDIT_SVC_AUTHZ_PASS, - request['client_id'], path) - return True diff --git a/ipaserver/custodia/httpd/server.py b/ipaserver/custodia/httpd/server.py index 235773249..218b66017 100644 --- a/ipaserver/custodia/httpd/server.py +++ b/ipaserver/custodia/httpd/server.py @@ -6,26 +6,19 @@ import errno import os import shutil import socket -import ssl import struct import sys import warnings +from http.server import BaseHTTPRequestHandler +from socketserver import ForkingTCPServer, BaseServer +from urllib.parse import parse_qs, unquote, urlparse + import six -from custodia import log -from ipaserver.custodia.compat import parse_qs, unquote, urlparse +from ipaserver.custodia import log from ipaserver.custodia.plugin import HTTPError -# pylint: disable=import-error,no-name-in-module -if six.PY2: - from BaseHTTPServer import BaseHTTPRequestHandler - from SocketServer import ForkingTCPServer, BaseServer -else: - from http.server import BaseHTTPRequestHandler - from socketserver import ForkingTCPServer, BaseServer -# pylint: enable=import-error,no-name-in-module - try: from systemd import daemon as sd # pylint: disable=import-error except ImportError: @@ -120,56 +113,6 @@ class ForkingUnixHTTPServer(ForkingHTTPServer): pass -class ForkingTLSServer(ForkingHTTPServer): - def __init__(self, server_address, handler_class, config, context=None, - bind_and_activate=True): - ForkingHTTPServer.__init__(self, server_address, handler_class, config, - bind_and_activate=bind_and_activate) - if context is None: - try: - self._context = self._mkcontext() - except Exception as e: - logger.error( - "Failed to create a SSLContext for TLS server: %s", e - ) - raise - else: - self._context = context - - def _mkcontext(self): - certfile = self.config.get('tls_certfile') - keyfile = self.config.get('tls_keyfile') - cafile = self.config.get('tls_cafile') - capath = self.config.get('tls_capath') - if self.config.get('tls_verify_client', False): - verifymode = ssl.CERT_REQUIRED - else: - verifymode = ssl.CERT_NONE - - if not certfile: - raise ValueError('tls_certfile is not set.') - - logger.info( - "Creating SSLContext for TLS server (cafile: '%s', capath: '%s', " - "verify client: %s).", - cafile, capath, verifymode == ssl.CERT_REQUIRED - ) - context = ssl.create_default_context( - ssl.Purpose.CLIENT_AUTH, - cafile=cafile, - capath=capath) - context.verify_mode = verifymode - logger.info( - "Loading cert chain '%s' (keyfile: '%s')", certfile, keyfile) - context.load_cert_chain(certfile, keyfile) - return context - - def get_request(self): - conn, client_addr = self.socket.accept() - sslconn = self._context.wrap_socket(conn, server_side=True) - return sslconn, client_addr - - class HTTPRequestHandler(BaseHTTPRequestHandler): """ @@ -515,11 +458,6 @@ class HTTPServer: address = (host, int(port)) logger.info('Serving on %s (HTTP)', url.netloc) serverclass = ForkingHTTPServer - elif url.scheme == 'https': - host, port = url.netloc.split(":") - address = (host, int(port)) - logger.info('Serving on %s (HTTPS)', url.netloc) - serverclass = ForkingTLSServer else: raise ValueError('Unknown URL Scheme: %s' % url.scheme) return serverclass, address diff --git a/ipaserver/custodia/plugin.py b/ipaserver/custodia/plugin.py index 08659e172..45243ac74 100644 --- a/ipaserver/custodia/plugin.py +++ b/ipaserver/custodia/plugin.py @@ -2,6 +2,7 @@ from __future__ import absolute_import import abc +import configparser import grp import inspect import json @@ -13,7 +14,6 @@ from jwcrypto.common import json_encode import six -from .compat import configparser from .log import CustodiaLoggingAdapter, auditlog, getLogger diff --git a/ipaserver/custodia/secrets.py b/ipaserver/custodia/secrets.py index 01f805b23..b47a25e52 100644 --- a/ipaserver/custodia/secrets.py +++ b/ipaserver/custodia/secrets.py @@ -5,7 +5,7 @@ import json import os from base64 import b64decode, b64encode -from custodia import log +from ipaserver.custodia import log from ipaserver.custodia.message.common import UnallowedMessage from ipaserver.custodia.message.common import UnknownMessageType from ipaserver.custodia.message.formats import Validator diff --git a/ipaserver/custodia/server/__init__.py b/ipaserver/custodia/server/__init__.py index ada9e1a70..5face3733 100644 --- a/ipaserver/custodia/server/__init__.py +++ b/ipaserver/custodia/server/__init__.py @@ -8,7 +8,7 @@ import pkg_resources import six -from custodia import log +from ipaserver.custodia import log from ipaserver.custodia.httpd.server import HTTPServer from .args import default_argparser diff --git a/ipaserver/custodia/server/config.py b/ipaserver/custodia/server/config.py index e8663dce9..ee6aab7aa 100644 --- a/ipaserver/custodia/server/config.py +++ b/ipaserver/custodia/server/config.py @@ -1,14 +1,11 @@ # Copyright (C) 2015-2017 Custodia Project Contributors - see LICENSE file from __future__ import absolute_import +import configparser import glob import os import socket - -import six - -from ipaserver.custodia.compat import configparser -from ipaserver.custodia.compat import url_escape +from urllib.parse import quote as url_escape class CustodiaConfig: @@ -54,9 +51,6 @@ class CustodiaConfig: for k, v in os.environ.items(): if set(v).intersection('\r\n\x00'): continue - if six.PY2: - k = k.decode('utf-8', 'replace') - v = v.decode('utf-8', 'replace') parser.set(u'ENV', k, v.replace(u'$', u'$$')) # default globals diff --git a/ipaserver/secrets/service.py b/ipaserver/secrets/service.py index 36d5a444e..88d5b81a7 100644 --- a/ipaserver/secrets/service.py +++ b/ipaserver/secrets/service.py @@ -1,7 +1,7 @@ # Copyright (C) 2017 IPA Project Contributors, see COPYING for license import argparse -import custodia.server # pylint: disable=relative-import +import ipaserver.custodia.server # pylint: disable=relative-import argparser = argparse.ArgumentParser( @@ -23,7 +23,7 @@ argparser.add_argument( def main(): - return custodia.server.main(argparser) + return ipaserver.custodia.server.main(argparser) if __name__ == '__main__': diff --git a/ipaserver/setup.py b/ipaserver/setup.py index 2d6fd5242..f2725a1d0 100644 --- a/ipaserver/setup.py +++ b/ipaserver/setup.py @@ -23,30 +23,6 @@ Python-level packaging using setuptools from os.path import abspath, dirname import sys -custodia_authenticators = [ - 'IPAInterface = ipaserver.custodia.ipa.interface:IPAInterface', - ('SimpleCredsAuth = ' - 'ipaserver.custodia.httpd.authenticators:SimpleCredsAuth'), -] - -custodia_authorizers = [ - 'SimplePathAuthz = ipaserver.custodia.httpd.authorizers:SimplePathAuthz', - 'UserNameSpace = ipaserver.custodia.httpd.authorizers:UserNameSpace', - 'KEMKeysStore = ipaserver.custodia.message.kem:KEMKeysStore', - 'IPAKEMKeys = ipaserver.secrets.kem:IPAKEMKeys', -] - -custodia_clients = [ - 'KEMClient = ipaserver.custodia.client:CustodiaKEMClient', - 'SimpleClient = ipaserver.custodia.client:CustodiaSimpleClient', -] - -custodia_consumers = [ - 'Forwarder = ipaserver.custodia.forwarder:Forwarder', - 'Secrets = ipaserver.custodia.secrets:Secrets', - 'Root = ipaserver.custodia.root:Root', -] - if __name__ == '__main__': # include ../ for ipasetup.py @@ -95,10 +71,25 @@ if __name__ == '__main__': "python-ldap", ], entry_points={ - 'ipaserver.custodia.authenticators': custodia_authenticators, - 'ipaserver.custodia.authorizers': custodia_authorizers, - 'ipaserver.custodia.clients': custodia_clients, - 'ipaserver.custodia.consumers': custodia_consumers, + 'ipaserver.custodia.authenticators': [ + ('SimpleCredsAuth = ' + 'ipaserver.custodia.httpd.authenticators:SimpleCredsAuth'), + ('SimpleHeaderAuth = ' + 'custodia.httpd.authenticators:SimpleHeaderAuth'), + ], + 'ipaserver.custodia.authorizers': [ + 'IPAKEMKeys = ipaserver.secrets.kem:IPAKEMKeys', + ], + 'ipaserver.custodia.clients': [ + 'KEMClient = ipaserver.custodia.client:CustodiaKEMClient', + ('SimpleClient = ' + 'ipaserver.custodia.client:CustodiaSimpleClient'), + ], + 'ipaserver.custodia.consumers': [ + 'Forwarder = ipaserver.custodia.forwarder:Forwarder', + 'Secrets = ipaserver.custodia.secrets:Secrets', + 'Root = ipaserver.custodia.root:Root', + ], 'ipaserver.custodia.stores': [ 'IPASecStore = ipaserver.secrets.store:IPASecStore', ],