Commit 83e06ad5 authored by Rafael Monnerat's avatar Rafael Monnerat

erp5_certificate_authority: Update test for Person/Certificate Login

parent c2054c7c
...@@ -72,9 +72,11 @@ class CertificateLoginMixin: ...@@ -72,9 +72,11 @@ class CertificateLoginMixin:
certificate_dict = { certificate_dict = {
"common_name" : self.getReference() "common_name" : self.getReference()
} }
if self.getReference and self.getSourceReference(): if self.getReference() and self.getSourceReference():
if csr is not None:
raise ValueError("This certificate already")
certificate_dict["id"] = self.getSourceReference() certificate_dict["id"] = self.getSourceReference()
crt_pem = caucase_connector.getCertificate(self.getSourceReference()) crt_pem = caucase_connector.getCertificate(int(self.getSourceReference()))
certificate_dict["certificate"] = crt_pem certificate_dict["certificate"] = crt_pem
# We should assert that reference is the CN of crt_pem # We should assert that reference is the CN of crt_pem
return certificate_dict return certificate_dict
...@@ -111,7 +113,7 @@ class CertificateLoginMixin: ...@@ -111,7 +113,7 @@ class CertificateLoginMixin:
else: else:
return self._getCertificate(csr=csr) return self._getCertificate(csr=csr)
def _revokeCertificate(self): def _revokeCertificate(self, key_pem=None):
if self.getDestinationReference() is not None or ( if self.getDestinationReference() is not None or (
self.getReference() is not None and self.getSourceReference() is None self.getReference() is not None and self.getSourceReference() is None
): ):
...@@ -119,12 +121,14 @@ class CertificateLoginMixin: ...@@ -119,12 +121,14 @@ class CertificateLoginMixin:
if self.getSourceReference() is not None: if self.getSourceReference() is not None:
caucase_connector = self._getCaucaseConnector() caucase_connector = self._getCaucaseConnector()
crt_pem = caucase_connector.getCertificate(self.getSourceReference()) crt_pem = caucase_connector.getCertificate(int(self.getSourceReference()))
caucase_connector.revokeCertificate(crt_pem) if key_pem is None:
return caucase_connector.revokeCertificate(crt_pem, key_pem)
return caucase_connector.revokeCertificate(crt_pem)
else: else:
raise ValueError("No certificate found to revoke!") raise ValueError("No certificate found to revoke!")
security.declarePrivate('revokeCertificate') security.declarePrivate('revokeCertificate')
def revokeCertificate(self): def revokeCertificate(self, key_pem=None):
"""Revokes existing certificate""" """Revokes existing certificate"""
self._revokeCertificate() self._revokeCertificate(key_pem=key_pem)
\ No newline at end of file \ No newline at end of file
...@@ -27,15 +27,20 @@ ...@@ -27,15 +27,20 @@
# #
############################################################################## ##############################################################################
import os #import os
import random import random
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeCaucaseTestCase import ERP5TypeCaucaseTestCase
from Products.ERP5Type.Core.Workflow import ValidationFailed from Products.ERP5Type.Core.Workflow import ValidationFailed
from AccessControl import Unauthorized from AccessControl import Unauthorized
from caucase.client import CaucaseHTTPError
class TestPersonCertificateLogin(ERP5TypeTestCase): from cryptography import x509
from cryptography.x509.oid import NameOID
class TestPersonCertificateLogin(ERP5TypeCaucaseTestCase):
def afterSetUp(self): def afterSetUp(self):
self.setUpCaucase()
if getattr(self.portal.portal_types.Person, if getattr(self.portal.portal_types.Person,
'user_can_see_himself', None) is None: 'user_can_see_himself', None) is None:
self.portal.portal_types.Person.newContent( self.portal.portal_types.Person.newContent(
...@@ -45,9 +50,6 @@ class TestPersonCertificateLogin(ERP5TypeTestCase): ...@@ -45,9 +50,6 @@ class TestPersonCertificateLogin(ERP5TypeTestCase):
role_base_category_script_id="ERP5Type_getSecurityCategoryFromSelf", role_base_category_script_id="ERP5Type_getSecurityCategoryFromSelf",
role_base_category="group", role_base_category="group",
portal_type="Role Information") portal_type="Role Information")
if "TEST_CA_PATH" in os.environ:
self.portal.portal_certificate_authority.certificate_authority_path = \
os.environ['TEST_CA_PATH']
def getBusinessTemplateList(self): def getBusinessTemplateList(self):
return ('erp5_base', 'erp5_certificate_authority') return ('erp5_base', 'erp5_certificate_authority')
...@@ -76,8 +78,10 @@ class TestPersonCertificateLogin(ERP5TypeTestCase): ...@@ -76,8 +78,10 @@ class TestPersonCertificateLogin(ERP5TypeTestCase):
self.assertNotEqual(certificate_login.getReference(), login) self.assertNotEqual(certificate_login.getReference(), login)
self.assertTrue(certificate_login.getReference().startswith("CERT")) self.assertTrue(certificate_login.getReference().startswith("CERT"))
self.assertIn('CN=%s' % certificate_login.getReference(), certificate['certificate']) ssl_certificate = x509.load_pem_x509_certificate(certificate['certificate'])
self.assertNotIn('CN=%s' % user_id, certificate['certificate']) self.assertEqual(len(ssl_certificate.subject), 1)
cn = [i.value for i in ssl_certificate.subject if i.oid == NameOID.COMMON_NAME][0]
self.assertEqual(certificate_login.getReference().decode("UTF-8"), cn)
def test_person_duplicated_login(self): def test_person_duplicated_login(self):
user_id, login = self._createPerson() user_id, login = self._createPerson()
...@@ -96,8 +100,11 @@ class TestPersonCertificateLogin(ERP5TypeTestCase): ...@@ -96,8 +100,11 @@ class TestPersonCertificateLogin(ERP5TypeTestCase):
self.assertNotEqual(certificate_login.getReference(), user_id) self.assertNotEqual(certificate_login.getReference(), user_id)
self.assertNotEqual(certificate_login.getReference(), login) self.assertNotEqual(certificate_login.getReference(), login)
self.assertTrue(certificate_login.getReference().startswith("CERT")) self.assertTrue(certificate_login.getReference().startswith("CERT"))
self.assertIn('CN=%s' % certificate_login.getReference(), certificate['certificate'])
self.assertNotIn('CN=%s' % user_id, certificate['certificate']) ssl_certificate = x509.load_pem_x509_certificate(certificate['certificate'])
self.assertEqual(len(ssl_certificate.subject), 1)
cn = [i.value for i in ssl_certificate.subject if i.oid == NameOID.COMMON_NAME][0]
self.assertEqual(certificate_login.getReference().decode("UTF-8"), cn)
# ERP5 Login dont conflicts # ERP5 Login dont conflicts
person.newContent(portal_type='ERP5 Login', person.newContent(portal_type='ERP5 Login',
...@@ -118,9 +125,11 @@ class TestPersonCertificateLogin(ERP5TypeTestCase): ...@@ -118,9 +125,11 @@ class TestPersonCertificateLogin(ERP5TypeTestCase):
self.assertNotEqual(certificate_login.getReference(), login) self.assertNotEqual(certificate_login.getReference(), login)
self.assertTrue(certificate_login.getReference().startswith("CERT")) self.assertTrue(certificate_login.getReference().startswith("CERT"))
self.assertIn('CN=%s' % certificate_login.getReference(), certificate['certificate']) ssl_certificate = x509.load_pem_x509_certificate(certificate['certificate'])
self.assertNotIn('CN=%s' % user_id, certificate['certificate']) self.assertEqual(len(ssl_certificate.subject), 1)
self.assertNotIn('CN=%s' % login, certificate['certificate']) cn = [i.value for i in ssl_certificate.subject if i.oid == NameOID.COMMON_NAME][0]
self.assertEqual(certificate_login.getReference().decode("UTF-8"), cn)
self.assertEqual(certificate_login.getValidationState(), "validated") self.assertEqual(certificate_login.getValidationState(), "validated")
new_certificate = person.generateCertificate() new_certificate = person.generateCertificate()
...@@ -140,10 +149,11 @@ class TestPersonCertificateLogin(ERP5TypeTestCase): ...@@ -140,10 +149,11 @@ class TestPersonCertificateLogin(ERP5TypeTestCase):
self.assertTrue(new_certificate_login.getReference().startswith("CERT")) self.assertTrue(new_certificate_login.getReference().startswith("CERT"))
self.assertIn('CN=%s' % new_certificate_login.getReference(), new_certificate['certificate']) ssl_certificate = x509.load_pem_x509_certificate(new_certificate['certificate'])
self.assertNotIn('CN=%s' % user_id, new_certificate['certificate']) self.assertEqual(len(ssl_certificate.subject), 1)
self.assertNotIn('CN=%s' % login, new_certificate['certificate']) cn = [i.value for i in ssl_certificate.subject if i.oid == NameOID.COMMON_NAME][0]
self.assertNotIn('CN=%s' % certificate_login.getReference(), new_certificate['certificate']) self.assertEqual(new_certificate_login.getReference().decode("UTF-8"), cn)
self.assertEqual(new_certificate_login.getValidationState(), "validated") self.assertEqual(new_certificate_login.getValidationState(), "validated")
def test_person_generate_certificate_for_another(self): def test_person_generate_certificate_for_another(self):
...@@ -192,8 +202,12 @@ class TestPersonCertificateLogin(ERP5TypeTestCase): ...@@ -192,8 +202,12 @@ class TestPersonCertificateLogin(ERP5TypeTestCase):
self.assertTrue(certificate_login.getReference().startswith("CERT")) self.assertTrue(certificate_login.getReference().startswith("CERT"))
self.assertIn('CN=%s' % certificate_login.getReference(), certificate_dict['certificate']) ssl_certificate = x509.load_pem_x509_certificate(certificate_dict['certificate'])
self.assertNotIn('CN=%s' % person.getUserId(), certificate_dict['certificate']) self.assertEqual(len(ssl_certificate.subject), 1)
cn_list = [i.value for i in ssl_certificate.subject if i.oid == NameOID.COMMON_NAME]
self.assertEqual(len(cn_list), 1)
self.assertEqual(certificate_login.getReference().decode("UTF-8"), cn_list[0])
self.assertEqual(certificate_login.getValidationState(), "draft") self.assertEqual(certificate_login.getValidationState(), "draft")
certificate_login.validate() certificate_login.validate()
...@@ -213,8 +227,11 @@ class TestPersonCertificateLogin(ERP5TypeTestCase): ...@@ -213,8 +227,11 @@ class TestPersonCertificateLogin(ERP5TypeTestCase):
# Reference is reset while setting the generate the certificate. # Reference is reset while setting the generate the certificate.
self.assertTrue(certificate_login.getReference().startswith("CERT")) self.assertTrue(certificate_login.getReference().startswith("CERT"))
self.assertIn('CN=%s' % certificate_login.getReference(), certificate_dict['certificate']) ssl_certificate = x509.load_pem_x509_certificate(certificate_dict['certificate'])
self.assertNotIn('CN=%s' % person.getUserId(), certificate_dict['certificate']) self.assertEqual(len(ssl_certificate.subject), 1)
cn_list = [i.value for i in ssl_certificate.subject if i.oid == NameOID.COMMON_NAME]
self.assertEqual(len(cn_list), 1)
self.assertEqual(certificate_login.getReference().decode("UTF-8"), cn_list[0])
self.assertEqual(certificate_login.getValidationState(), "draft") self.assertEqual(certificate_login.getValidationState(), "draft")
certificate_login.validate() certificate_login.validate()
...@@ -231,11 +248,25 @@ class TestPersonCertificateLogin(ERP5TypeTestCase): ...@@ -231,11 +248,25 @@ class TestPersonCertificateLogin(ERP5TypeTestCase):
# Reference is reset while setting the generate the certificate. # Reference is reset while setting the generate the certificate.
self.assertTrue(reference.startswith("CERT")) self.assertTrue(reference.startswith("CERT"))
self.assertIn('CN=%s' % reference, certificate_dict['certificate']) # If no csr is provided, the private key is generated by the master
self.assertNotIn('CN=%s' % person.getUserId(), certificate_dict['certificate']) # this is to provide backward compatibility with old clients
self.assertIn("key", certificate_dict.keys())
ssl_certificate = x509.load_pem_x509_certificate(certificate_dict['certificate'])
self.assertEqual(len(ssl_certificate.subject), 1)
cn_list = [i.value for i in ssl_certificate.subject if i.oid == NameOID.COMMON_NAME]
self.assertEqual(len(cn_list), 1)
self.assertEqual(certificate_login.getReference().decode("UTF-8"), cn_list[0])
self.assertEqual(certificate_login.getValidationState(), "draft") self.assertEqual(certificate_login.getValidationState(), "draft")
self.assertRaises(ValueError, certificate_login.getCertificate) same_certificate_dict = certificate_login.getCertificate()
self.assertEqual(certificate_dict['certificate'], same_certificate_dict['certificate'])
# If no csr is provided, the private key is generated by the master
# this is to provide backward compatibility with old clients
self.assertNotIn("key", same_certificate_dict.keys())
self.assertRaises(ValueError, certificate_login.getCertificate, "some_csr_string")
def test_certificate_login_revoke(self): def test_certificate_login_revoke(self):
person = self.portal.person_module.newContent(portal_type='Person') person = self.portal.person_module.newContent(portal_type='Person')
...@@ -246,16 +277,49 @@ class TestPersonCertificateLogin(ERP5TypeTestCase): ...@@ -246,16 +277,49 @@ class TestPersonCertificateLogin(ERP5TypeTestCase):
certificate_dict = certificate_login.getCertificate() certificate_dict = certificate_login.getCertificate()
reference = certificate_login.getReference() reference = certificate_login.getReference()
self.assertTrue(reference.startswith("CERT")) self.assertTrue(reference.startswith("CERT"))
self.assertIn('CN=%s' % reference, certificate_dict['certificate'])
self.assertNotEqual(certificate_login.getDestinationReference(), None) ssl_certificate = x509.load_pem_x509_certificate(certificate_dict['certificate'])
self.assertEqual(len(ssl_certificate.subject), 1)
cn_list = [i.value for i in ssl_certificate.subject if i.oid == NameOID.COMMON_NAME]
self.assertEqual(len(cn_list), 1)
self.assertEqual(certificate_login.getReference().decode("UTF-8"), cn_list[0])
self.assertEqual(certificate_login.getDestinationReference(), None)
self.assertNotEqual(certificate_login.getSourceReference(), None)
self.assertEqual(None, certificate_login.revokeCertificate()) self.assertEqual(None, certificate_login.revokeCertificate())
self.assertEqual(certificate_login.getDestinationReference(), None) self.assertEqual(certificate_login.getDestinationReference(), None)
self.assertEqual(reference, certificate_login.getReference()) self.assertEqual(reference, certificate_login.getReference())
# Revoke again must raise # Revoke again must raise
self.assertRaises(CaucaseHTTPError, certificate_login.revokeCertificate)
def test_certificate_login_revoke_providing_key(self):
person = self.portal.person_module.newContent(portal_type='Person')
certificate_login = person.newContent(portal_type='Certificate Login')
self.assertEqual(certificate_login.getReference(), None)
self.assertRaises(ValueError, certificate_login.revokeCertificate) self.assertRaises(ValueError, certificate_login.revokeCertificate)
certificate_dict = certificate_login.getCertificate()
reference = certificate_login.getReference()
self.assertTrue(reference.startswith("CERT"))
ssl_certificate = x509.load_pem_x509_certificate(certificate_dict['certificate'])
self.assertEqual(len(ssl_certificate.subject), 1)
cn_list = [i.value for i in ssl_certificate.subject if i.oid == NameOID.COMMON_NAME]
self.assertEqual(len(cn_list), 1)
self.assertEqual(certificate_login.getReference().decode("UTF-8"), cn_list[0])
self.assertEqual(certificate_login.getDestinationReference(), None)
self.assertNotEqual(certificate_login.getSourceReference(), None)
self.assertEqual(None, certificate_login.revokeCertificate(certificate_dict['key']))
self.assertEqual(certificate_login.getDestinationReference(), None)
self.assertEqual(reference, certificate_login.getReference())
# Revoke again must raise
self.assertRaises(CaucaseHTTPError, certificate_login.revokeCertificate, certificate_dict['key'])
def test_certificate_login_revoke_backward_compatibility(self): def test_certificate_login_revoke_backward_compatibility(self):
person = self.portal.person_module.newContent(portal_type='Person') person = self.portal.person_module.newContent(portal_type='Person')
certificate_login = person.newContent(portal_type='Certificate Login') certificate_login = person.newContent(portal_type='Certificate Login')
...@@ -265,14 +329,36 @@ class TestPersonCertificateLogin(ERP5TypeTestCase): ...@@ -265,14 +329,36 @@ class TestPersonCertificateLogin(ERP5TypeTestCase):
certificate_dict = certificate_login.getCertificate() certificate_dict = certificate_login.getCertificate()
reference = certificate_login.getReference() reference = certificate_login.getReference()
self.assertTrue(reference.startswith("CERT")) self.assertTrue(reference.startswith("CERT"))
self.assertIn('CN=%s' % reference, certificate_dict['certificate'])
self.assertNotEqual(certificate_login.getDestinationReference(), None) ssl_certificate = x509.load_pem_x509_certificate(certificate_dict['certificate'])
self.assertEqual(len(ssl_certificate.subject), 1)
cn_list = [i.value for i in ssl_certificate.subject if i.oid == NameOID.COMMON_NAME]
self.assertEqual(len(cn_list), 1)
self.assertEqual(certificate_login.getReference().decode("UTF-8"), cn_list[0])
self.assertEqual(certificate_login.getDestinationReference(), None)
self.assertNotEqual(certificate_login.getSourceReference(), None)
# Older implementation wont set it on the Certificate login # Older implementation wont set it on the Certificate login
certificate_login.setDestinationReference(None) certificate_login.setDestinationReference(None)
self.assertEqual(None, certificate_login.revokeCertificate()) certificate_login.setSourceReference(None)
self.assertEqual(certificate_login.getDestinationReference(), None)
self.assertEqual(reference, certificate_login.getReference()) # Still raise since it has no valid certificate anymore
self.assertRaises(ValueError, certificate_login.revokeCertificate)
def test_certificate_login_revoke_backward_compatibility_with_old_serial(self):
person = self.portal.person_module.newContent(portal_type='Person')
certificate_login = person.newContent(portal_type='Certificate Login')
self.assertEqual(certificate_login.getReference(), None)
self.assertRaises(ValueError, certificate_login.revokeCertificate)
certificate_login.getCertificate()
reference = certificate_login.getReference()
self.assertTrue(reference.startswith("CERT"))
# Older implementation, using openssl, would have destination reference set
# this just raise since it cannot be managed by caucase
certificate_login.setDestinationReference("SOMESERIAL")
# Still raise since it has no valid certificate anymore # Still raise since it has no valid certificate anymore
self.assertRaises(ValueError, certificate_login.revokeCertificate) self.assertRaises(ValueError, certificate_login.revokeCertificate)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment