diff options
Diffstat (limited to 'ipsilon/providers')
-rwxr-xr-x | ipsilon/providers/saml2/certs.py | 57 | ||||
-rwxr-xr-x | ipsilon/providers/saml2/metadata.py | 159 | ||||
-rwxr-xr-x | ipsilon/providers/saml2/provider.py | 20 | ||||
-rwxr-xr-x | ipsilon/providers/saml2idp.py | 4 |
4 files changed, 6 insertions, 234 deletions
diff --git a/ipsilon/providers/saml2/certs.py b/ipsilon/providers/saml2/certs.py deleted file mode 100755 index dc08e08..0000000 --- a/ipsilon/providers/saml2/certs.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/python -# -# Copyright (C) 2014 Simo Sorce <simo@redhat.com> -# -# see file 'COPYING' for use and warranty information -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -from subprocess import Popen -import os -import string - - -class Certificate(object): - - def __init__(self, path=None): - self.subject = None - self.path = path - self.key = None - self.cert = None - - def generate(self, prefix, subject): - self.key = '%s.key' % prefix - self.cert = '%s.pem' % prefix - self.subject = '/CN=%s' % subject - command = ['openssl', - 'req', '-x509', '-batch', '-days', '1825', - '-newkey', 'rsa:2048', '-nodes', '-subj', self.subject, - '-keyout', os.path.join(self.path, self.key), - '-out', os.path.join(self.path, self.cert)] - proc = Popen(command) - proc.wait() - - def get_cert(self): - if not self.cert: - raise NameError('Invalid certificate name: %s' % self.cert) - with open(os.path.join(self.path, self.cert), 'r') as f: - cert = f.readlines() - - #poor man stripping of BEGIN/END lines - if cert[0] == '-----BEGIN CERTIFICATE-----\n': - cert = cert[1:] - if cert[-1] == '-----END CERTIFICATE-----\n': - cert = cert[:-1] - - return string.join(cert) diff --git a/ipsilon/providers/saml2/metadata.py b/ipsilon/providers/saml2/metadata.py deleted file mode 100755 index 0effd4c..0000000 --- a/ipsilon/providers/saml2/metadata.py +++ /dev/null @@ -1,159 +0,0 @@ -#!/usr/bin/python -# -# Copyright (C) 2014 Simo Sorce <simo@redhat.com> -# -# see file 'COPYING' for use and warranty information -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -from ipsilon.providers.saml2.certs import Certificate -from lxml import etree -import lasso - - -EDESC = '{%s}EntityDescriptor' % lasso.SAML2_METADATA_HREF -NSMAP = { - 'md': lasso.SAML2_METADATA_HREF, - 'ds': lasso.DS_HREF -} - -IDPDESC = 'IDPSSODescriptor' -SPDESC = 'SPSSODescriptor' - -IDP_ROLE = 'idp' -SP_ROLE = 'sp' - -SSO_SERVICE = 'SingleSignOnService' -LOGOUT_SERVICE = 'SingleLogoutService' -ASSERTION_SERVICE = 'AssertionConsumerService' - - -def mdElement(_parent, _tag, **kwargs): - tag = '{%s}%s' % (lasso.SAML2_METADATA_HREF, _tag) - return etree.SubElement(_parent, tag, **kwargs) - - -def dsElement(_parent, _tag, **kwargs): - tag = '{%s}%s' % (lasso.DS_HREF, _tag) - return etree.SubElement(_parent, tag, **kwargs) - - -class Metadata(object): - - def __init__(self, role=None): - self.root = etree.Element(EDESC, nsmap=NSMAP) - self.entityid = None - self.role = None - self.set_role(role) - - def set_entity_id(self, url): - self.entityid = url - self.root.set('entityID', url) - - def set_role(self, role): - if role is None: - return - elif role == IDP_ROLE: - description = IDPDESC - elif role == SP_ROLE: - description = SPDESC - else: - raise ValueError('invalid role: %s' % role) - self.role = mdElement(self.root, description) - self.role.set('protocolSupportEnumeration', lasso.SAML2_PROTOCOL_HREF) - return self.role - - def add_cert(self, certdata, use): - desc = mdElement(self.role, 'KeyDescriptor') - desc.set('use', use) - info = dsElement(desc, 'KeyInfo') - data = dsElement(info, 'X509Data') - cert = dsElement(data, 'X509Certificate') - cert.text = certdata - - def add_certs(self, signcert=None, enccert=None): - if signcert: - self.add_cert(signcert.get_cert(), 'signing') - if enccert: - self.add_cert(enccert.get_cert(), 'encryption') - - def add_service(self, svctype, binding, location): - svc = mdElement(self.role, svctype) - svc.set('Binding', binding) - svc.set('Location', location) - - def add_allowed_name_format(self, name_format): - nameidfmt = mdElement(self.role, 'NameIDFormat') - nameidfmt.text = name_format - - def output(self, path): - data = etree.tostring(self.root, xml_declaration=True, - encoding='UTF-8', pretty_print=True) - with open(path, 'w') as f: - f.write(data) - - -if __name__ == '__main__': - from ipsilon.providers.saml2.provider import NAMEID_MAP - import tempfile - import shutil - import os - - tmpdir = tempfile.mkdtemp() - - try: - # Test IDP generation - sign_cert = Certificate(tmpdir) - sign_cert.generate('idp-signing-cert', 'idp.ipsilon.example.com') - enc_cert = Certificate(tmpdir) - enc_cert.generate('idp-encryption-cert', 'idp.ipsilon.example.com') - idp = Metadata() - idp.set_entity_id('https://ipsilon.example.com/idp/metadata') - idp.set_role(IDP_ROLE) - idp.add_certs(sign_cert, enc_cert) - idp.add_service(SSO_SERVICE, lasso.SAML2_METADATA_BINDING_POST, - 'https://ipsilon.example.com/idp/saml2/POST') - idp.add_service(SSO_SERVICE, lasso.SAML2_METADATA_BINDING_REDIRECT, - 'https://ipsilon.example.com/idp/saml2/Redirect') - for k in NAMEID_MAP: - idp.add_allowed_name_format(NAMEID_MAP[k]) - md_file = os.path.join(tmpdir, 'metadata.xml') - idp.output(md_file) - with open(md_file) as fd: - text = fd.read() - print '==================== IDP ====================' - print text - print '=============================================' - - # Test SP generation - sign_cert = Certificate(tmpdir) - sign_cert.generate('sp-signing-cert', 'sp.ipsilon.example.com') - sp = Metadata() - sp.set_entity_id('https://ipsilon.example.com/samlsp/metadata') - sp.set_role(SP_ROLE) - sp.add_certs(sign_cert) - sp.add_service(LOGOUT_SERVICE, lasso.SAML2_METADATA_BINDING_REDIRECT, - 'https://ipsilon.example.com/samlsp/logout') - sp.add_service(ASSERTION_SERVICE, lasso.SAML2_METADATA_BINDING_POST, - 'https://ipsilon.example.com/samlsp/postResponse') - md_file = os.path.join(tmpdir, 'metadata.xml') - sp.output(md_file) - with open(md_file) as fd: - text = fd.read() - print '===================== SP ====================' - print text - print '=============================================' - - finally: - shutil.rmtree(tmpdir) diff --git a/ipsilon/providers/saml2/provider.py b/ipsilon/providers/saml2/provider.py index 73ff005..7d47363 100755 --- a/ipsilon/providers/saml2/provider.py +++ b/ipsilon/providers/saml2/provider.py @@ -18,23 +18,11 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from ipsilon.providers.common import ProviderException +from ipsilon.tools.saml2metadata import SAML2_NAMEID_MAP import cherrypy import lasso -NAMEID_MAP = { - 'email': lasso.SAML2_NAME_IDENTIFIER_FORMAT_EMAIL, - 'encrypted': lasso.SAML2_NAME_IDENTIFIER_FORMAT_ENCRYPTED, - 'entity': lasso.SAML2_NAME_IDENTIFIER_FORMAT_ENTITY, - 'kerberos': lasso.SAML2_NAME_IDENTIFIER_FORMAT_KERBEROS, - 'persistent': lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT, - 'transient': lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT, - 'unspecified': lasso.SAML2_NAME_IDENTIFIER_FORMAT_UNSPECIFIED, - 'windows': lasso.SAML2_NAME_IDENTIFIER_FORMAT_WINDOWS, - 'x509': lasso.SAML2_NAME_IDENTIFIER_FORMAT_X509, -} - - class InvalidProviderId(ProviderException): def __init__(self, code): @@ -129,14 +117,14 @@ class ServiceProvider(object): def get_valid_nameid(self, nip): self._debug('Requested NameId [%s]' % (nip.format,)) if nip.format is None: - return NAMEID_MAP[self.default_nameid] + return SAML2_NAMEID_MAP[self.default_nameid] elif nip.format == lasso.SAML2_NAME_IDENTIFIER_FORMAT_UNSPECIFIED: - return NAMEID_MAP[self.default_nameid] + return SAML2_NAMEID_MAP[self.default_nameid] else: allowed = self.allowed_nameids self._debug('Allowed NameIds %s' % (repr(allowed))) for nameid in allowed: - if nip.format == NAMEID_MAP[nameid]: + if nip.format == SAML2_NAMEID_MAP[nameid]: return nip.format raise NameIdNotAllowed(nip.format) diff --git a/ipsilon/providers/saml2idp.py b/ipsilon/providers/saml2idp.py index 1922c53..87cc7f6 100755 --- a/ipsilon/providers/saml2idp.py +++ b/ipsilon/providers/saml2idp.py @@ -21,9 +21,9 @@ from ipsilon.providers.common import ProviderBase, ProviderPageBase from ipsilon.providers.common import FACILITY from ipsilon.providers.saml2.auth import AuthenticateRequest from ipsilon.providers.saml2.admin import AdminPage -from ipsilon.providers.saml2.certs import Certificate from ipsilon.providers.saml2.provider import IdentityProvider -from ipsilon.providers.saml2 import metadata +from ipsilon.tools.certs import Certificate +from ipsilon.tools import saml2metadata as metadata from ipsilon.util.user import UserSession from ipsilon.util.plugin import PluginObject import cherrypy |