Skip to content

Commit 3a67869

Browse files
Allow metadata signing with SP key specified as config value, not file
1 parent c44971e commit 3a67869

File tree

2 files changed

+55
-27
lines changed

2 files changed

+55
-27
lines changed

src/onelogin/saml2/settings.py

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -557,9 +557,21 @@ def get_sp_metadata(self):
557557
# Sign metadata
558558
if 'signMetadata' in self.__security and self.__security['signMetadata'] is not False:
559559
if self.__security['signMetadata'] is True:
560-
key_file_name = 'sp.key'
561-
cert_file_name = 'sp.crt'
560+
# Use the SP's normal key to sign the metadata:
561+
if not cert:
562+
raise OneLogin_Saml2_Error(
563+
'Cannot sign metadata: missing SP public key certificate.',
564+
OneLogin_Saml2_Error.PUBLIC_CERT_FILE_NOT_FOUND
565+
)
566+
cert_metadata = cert
567+
key_metadata = self.get_sp_key()
568+
if not key_metadata:
569+
raise OneLogin_Saml2_Error(
570+
'Cannot sign metadata: missing SP private key.',
571+
OneLogin_Saml2_Error.PRIVATE_KEY_FILE_NOT_FOUND
572+
)
562573
else:
574+
# Use a custom key to sign the metadata:
563575
if ('keyFileName' not in self.__security['signMetadata'] or
564576
'certFileName' not in self.__security['signMetadata']):
565577
raise OneLogin_Saml2_Error(
@@ -568,30 +580,28 @@ def get_sp_metadata(self):
568580
)
569581
key_file_name = self.__security['signMetadata']['keyFileName']
570582
cert_file_name = self.__security['signMetadata']['certFileName']
571-
key_metadata_file = self.__paths['cert'] + key_file_name
572-
cert_metadata_file = self.__paths['cert'] + cert_file_name
573-
574-
if not exists(key_metadata_file):
575-
raise OneLogin_Saml2_Error(
576-
'Private key file not found: %s',
577-
OneLogin_Saml2_Error.PRIVATE_KEY_FILE_NOT_FOUND,
578-
key_metadata_file
579-
)
583+
key_metadata_file = self.__paths['cert'] + key_file_name
584+
cert_metadata_file = self.__paths['cert'] + cert_file_name
580585

581-
if not exists(cert_metadata_file):
582-
raise OneLogin_Saml2_Error(
583-
'Public cert file not found: %s',
584-
OneLogin_Saml2_Error.PUBLIC_CERT_FILE_NOT_FOUND,
585-
cert_metadata_file
586-
)
587-
588-
f_metadata_key = open(key_metadata_file, 'r')
589-
key_metadata = f_metadata_key.read()
590-
f_metadata_key.close()
586+
try:
587+
with open(key_metadata_file, 'r') as f_metadata_key:
588+
key_metadata = f_metadata_key.read()
589+
except IOError:
590+
raise OneLogin_Saml2_Error(
591+
'Private key file not readable: %s',
592+
OneLogin_Saml2_Error.PRIVATE_KEY_FILE_NOT_FOUND,
593+
key_metadata_file
594+
)
591595

592-
f_metadata_cert = open(cert_metadata_file, 'r')
593-
cert_metadata = f_metadata_cert.read()
594-
f_metadata_cert.close()
596+
try:
597+
with open(cert_metadata_file, 'r') as f_metadata_cert:
598+
cert_metadata = f_metadata_cert.read()
599+
except IOError:
600+
raise OneLogin_Saml2_Error(
601+
'Public cert file not readable: %s',
602+
OneLogin_Saml2_Error.PUBLIC_CERT_FILE_NOT_FOUND,
603+
cert_metadata_file
604+
)
595605

596606
metadata = OneLogin_Saml2_Metadata.sign_metadata(metadata, key_metadata, cert_metadata)
597607

tests/src/OneLogin/saml2_tests/settings_test.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from os.path import dirname, join, exists, sep
88
import unittest
99

10+
from onelogin.saml2.errors import OneLogin_Saml2_Error
1011
from onelogin.saml2.settings import OneLogin_Saml2_Settings
1112
from onelogin.saml2.utils import OneLogin_Saml2_Utils
1213

@@ -371,8 +372,24 @@ def testGetSPMetadataSigned(self):
371372
if 'security' not in settings_info:
372373
settings_info['security'] = {}
373374
settings_info['security']['signMetadata'] = True
374-
settings = OneLogin_Saml2_Settings(settings_info)
375+
self.generateAndCheckMetadata(settings_info)
376+
377+
# Now try again with SP keys set directly in settings and not from files:
378+
del settings_info['custom_base_path']
379+
# Now the keys should not be found, so metadata generation won't work:
380+
with self.assertRaises(OneLogin_Saml2_Error):
381+
OneLogin_Saml2_Settings(settings_info).get_sp_metadata()
382+
# Set the keys in the settings:
383+
settings_info['sp']['x509cert'] = self.file_contents(join(self.data_path, 'customPath', 'certs', 'sp.crt'))
384+
settings_info['sp']['privateKey'] = self.file_contents(join(self.data_path, 'customPath', 'certs', 'sp.key'))
385+
self.generateAndCheckMetadata(settings_info)
375386

387+
def generateAndCheckMetadata(self, settings):
388+
"""
389+
Helper method: Given some settings, generate metadata and validate it
390+
"""
391+
if not isinstance(settings, OneLogin_Saml2_Settings):
392+
settings = OneLogin_Saml2_Settings(settings)
376393
metadata = settings.get_sp_metadata()
377394
self.assertIn('<md:SPSSODescriptor', metadata)
378395
self.assertIn('entityID="http://stuff.com/endpoints/metadata.php"', metadata)
@@ -385,6 +402,7 @@ def testGetSPMetadataSigned(self):
385402
self.assertIn('<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>', metadata)
386403
self.assertIn('<ds:Reference', metadata)
387404
self.assertIn('<ds:KeyInfo><ds:X509Data><ds:X509Certificate>', metadata)
405+
return metadata
388406

389407
def testGetSPMetadataSignedNoMetadataCert(self):
390408
"""
@@ -411,7 +429,7 @@ def testGetSPMetadataSignedNoMetadataCert(self):
411429
settings.get_sp_metadata()
412430
self.assertTrue(False)
413431
except Exception as e:
414-
self.assertIn('Private key file not found', e.message)
432+
self.assertIn('Private key file not readable', e.message)
415433

416434
settings_info['security']['signMetadata'] = {
417435
'keyFileName': 'sp.key',
@@ -422,7 +440,7 @@ def testGetSPMetadataSignedNoMetadataCert(self):
422440
settings.get_sp_metadata()
423441
self.assertTrue(False)
424442
except Exception as e:
425-
self.assertIn('Public cert file not found', e.message)
443+
self.assertIn('Public cert file not readable', e.message)
426444

427445
settings_info['security']['signMetadata'] = 'invalid_value'
428446
settings = OneLogin_Saml2_Settings(settings_info)

0 commit comments

Comments
 (0)