diff --git a/.gitignore b/.gitignore index fe7abf2..5286bb7 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ local/ .vscode/ .venv/ +build/ diff --git a/cepces/soap/__init__.py b/cepces/soap/__init__.py index 08bc55f..17f614f 100644 --- a/cepces/soap/__init__.py +++ b/cepces/soap/__init__.py @@ -20,6 +20,7 @@ NS_SOAP = 'http://www.w3.org/2003/05/soap-envelope' NS_ADDRESSING = 'http://www.w3.org/2005/08/addressing' +NS_WSSE = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' # ACTION_FAULT = 'http://www.w3.org/2005/08/addressing/fault' QNAME_FAULT = QName('http://www.w3.org/2003/05/soap-envelope', 'Fault') diff --git a/cepces/soap/auth.py b/cepces/soap/auth.py index 40c30cd..2557f71 100644 --- a/cepces/soap/auth.py +++ b/cepces/soap/auth.py @@ -27,6 +27,7 @@ from cepces.krb5 import types as ktypes from cepces.krb5.core import Context, Keytab, Principal from cepces.krb5.core import CredentialOptions, Credentials, CredentialCache +from cepces.soap.types import Security as WSSecurity, UsernameToken class Authentication(Base, metaclass=ABCMeta): @@ -152,7 +153,13 @@ def clientcertificate(self): return None def post_process(self, envelope): - raise NotImplementedError() + envelope.header.element.append(WSSecurity.create()) + + envelope.header.security.element.append(UsernameToken.create()) + envelope.header.security.usernametoken.username = self._username + envelope.header.security.usernametoken.password = self._password + + return envelope class TransportCertificateAuthentication(Authentication): diff --git a/cepces/soap/types.py b/cepces/soap/types.py index 2648495..a8b7f5d 100644 --- a/cepces/soap/types.py +++ b/cepces/soap/types.py @@ -21,7 +21,7 @@ # pylint: disable=invalid-name """This module contains common SOAP types.""" from xml.etree.ElementTree import Element, QName -from cepces.soap import NS_ADDRESSING, NS_SOAP +from cepces.soap import NS_ADDRESSING, NS_SOAP, NS_WSSE from cepces.xml import NS_XSI from cepces.xml.binding import XMLElement, XMLNode, XMLValue from cepces.xml.converter import StringConverter @@ -100,6 +100,43 @@ def create(): return element +class UsernameToken(XMLNode): + """WSSE UsernameToken.""" + username = XMLValue('Username', + converter=StringConverter, + namespace=NS_WSSE) + password = XMLValue('Password', + converter=StringConverter, + namespace=NS_WSSE) + + @staticmethod + def create(): + usernametoken = Element(QName(NS_WSSE, 'UsernameToken')) + + username = Element(QName(NS_WSSE, 'Username')) + usernametoken.append(username) + + password = Element(QName(NS_WSSE, 'Password')) + password.attrib[QName(NS_WSSE, 'Type' )] = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText' + usernametoken.append(password) + + return usernametoken + + +class Security(XMLNode): + """WSSE Security.""" + usernametoken = XMLElement('UsernameToken', + binder=UsernameToken, + namespace=NS_WSSE) + + @staticmethod + def create(): + security = Element(QName(NS_WSSE, 'Security')) + security.attrib[QName(NS_SOAP, 'mustUnderstand')] = '1' + + return security + + class Header(XMLNode): """SOAP Header.""" action = XMLValue('Action', @@ -122,6 +159,10 @@ class Header(XMLNode): namespace=NS_ADDRESSING, nillable=True) + security = XMLElement ('Security', + binder=Security, + namespace=NS_WSSE) + @staticmethod def create(): header = Element(QName(NS_SOAP, 'Header')) diff --git a/conf/cepces.conf.dist b/conf/cepces.conf.dist index 582851f..417d0fc 100644 --- a/conf/cepces.conf.dist +++ b/conf/cepces.conf.dist @@ -116,3 +116,14 @@ delegate=True # # Default: #keyfile = /path/to/openssl-keyfile.pem + +[usernamepassword] +# Use the following AD username in UPN notation. +# +# Default: +#username = user@your-ad.local + +# Use the following AD password. +# +# Default: +#password = ADpassword \ No newline at end of file