summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--keystone/contrib/federation/idp.py25
-rw-r--r--keystone/tests/test_v3_federation.py31
2 files changed, 49 insertions, 7 deletions
diff --git a/keystone/contrib/federation/idp.py b/keystone/contrib/federation/idp.py
index c9c20c910..49d6b67ed 100644
--- a/keystone/contrib/federation/idp.py
+++ b/keystone/contrib/federation/idp.py
@@ -398,14 +398,25 @@ def _sign_assertion(assertion):
'--id-attr:ID', 'Assertion']
try:
- file_path = fileutils.write_to_tempfile(assertion.to_string())
+ # NOTE(gyee): need to make the namespace prefixes explicit so
+ # they won't get reassigned when we wrap the assertion into
+ # SAML2 response
+ file_path = fileutils.write_to_tempfile(assertion.to_string(
+ nspair={'saml': saml2.NAMESPACE,
+ 'xmldsig': xmldsig.NAMESPACE}))
command_list.append(file_path)
- stdout = subprocess.check_output(command_list)
- except Exception as e:
- msg = _LE('Error when signing assertion, reason: %(reason)s')
- msg = msg % {'reason': e}
- LOG.error(msg)
- raise exception.SAMLSigningError(reason=e)
+ process = subprocess.Popen(command_list,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ close_fds=True)
+ stdout, stderr = process.communicate()
+ retcode = process.poll()
+ if retcode:
+ msg = _LE('Error when signing assertion, reason: %(reason)s')
+ msg = msg % {'reason': stderr}
+ LOG.error(msg)
+ raise exception.SAMLSigningError(reason=stderr)
finally:
try:
os.remove(file_path)
diff --git a/keystone/tests/test_v3_federation.py b/keystone/tests/test_v3_federation.py
index f06102123..202e61c98 100644
--- a/keystone/tests/test_v3_federation.py
+++ b/keystone/tests/test_v3_federation.py
@@ -1803,6 +1803,37 @@ class SAMLGenerationTests(FederationTests):
project_attribute = assertion[4][2]
self.assertEqual(self.PROJECT, project_attribute[0].text)
+ def test_assertion_using_explicit_namespace_prefixes(self):
+ class MockedPopen(object):
+ def __init__(self, *popenargs, **kwargs):
+ # the last option is the assertion file to be signed
+ filename = popenargs[0][-1]
+ with open(filename, 'r') as f:
+ self.stdout = f.read()
+
+ def communicate(self, *args, **kwargs):
+ # since we are not testing the signature itself, we can return
+ # the assertion as is without signing it
+ return (self.stdout, None)
+
+ def poll(self):
+ return 0
+
+ with mock.patch('subprocess.Popen',
+ side_effect=MockedPopen):
+ generator = keystone_idp.SAMLGenerator()
+ response = generator.samlize_token(self.ISSUER, self.RECIPIENT,
+ self.SUBJECT, self.ROLES,
+ self.PROJECT)
+ assertion_xml = response.assertion.to_string()
+ # make sure we have the proper tag and prefix for the assertion
+ # namespace
+ self.assertIn('<saml:Assertion', assertion_xml)
+ self.assertIn('xmlns:saml="' + saml2.NAMESPACE + '"',
+ assertion_xml)
+ self.assertIn('xmlns:xmldsig="' + xmldsig.NAMESPACE + '"',
+ assertion_xml)
+
def test_saml_signing(self):
"""Test that the SAML generator produces a SAML object.