def test_bad_scope_subset_does_not_validate(self): bad_subset_cert = Certificate( parent=self.root_cert, profile=self.profile, scope_definition=self.subset_scope_def, scope_version=self.subset_scope_def.version, scope_params=json.dumps({ "mainpartition": "a" * 32, "subpartition": "abracadabra" }), private_key=Key(), ) self.root_cert.sign_certificate(bad_subset_cert) bad_subset_cert.save() with self.assertRaises(CertificateScopeNotSubset): bad_subset_cert.check_certificate()
class CertificateTestCaseMixin(object): def setUp(self): self.profile = "testprofile" self.root_scope_def = ScopeDefinition.objects.create( id="rootcert", profile=self.profile, version=1, primary_scope_param_key="mainpartition", description="Root cert for ${mainpartition}.", read_filter_template="", write_filter_template="", read_write_filter_template="${mainpartition}", ) self.subset_scope_def = ScopeDefinition.objects.create( id="subcert", profile=self.profile, version=1, primary_scope_param_key="", description= "Subset cert under ${mainpartition} for ${subpartition}.", read_filter_template="${mainpartition}", write_filter_template="${mainpartition}:${subpartition}", read_write_filter_template="", ) self.root_cert = Certificate.generate_root_certificate( self.root_scope_def.id) self.subset_cert = Certificate( parent=self.root_cert, profile=self.profile, scope_definition=self.subset_scope_def, scope_version=self.subset_scope_def.version, scope_params=json.dumps({ "mainpartition": self.root_cert.id, "subpartition": "abracadabra" }), private_key=Key(), ) self.root_cert.sign_certificate(self.subset_cert) self.subset_cert.save()
def push_signed_client_certificate_chain(self, local_parent_cert, scope_definition_id, scope_params): # grab shared public key of server publickey_response = self._get_public_key() # request the server for a one-time-use nonce nonce_response = self._get_nonce() # build up data for csr certificate = Certificate( parent_id=local_parent_cert.id, profile=local_parent_cert.profile, scope_definition_id=scope_definition_id, scope_version=local_parent_cert.scope_version, scope_params=json.dumps(scope_params), public_key=Key( public_key_string=publickey_response.json()[0]['public_key']), salt=nonce_response.json()[ "id"] # for pushing signed certs, we use nonce as salt ) # add ID and signature to the certificate certificate.id = certificate.calculate_uuid() certificate.parent.sign_certificate(certificate) # serialize the chain for sending to server certificate_chain = list( local_parent_cert.get_descendants( include_self=True)) + [certificate] data = json.dumps( CertificateSerializer(certificate_chain, many=True).data) # client sends signed certificate chain to server self._push_certificate_chain(data) # if there are no errors, we can save the pushed certificate certificate.save() return certificate
class NetworkSyncConnectionTestCase(TestCase): def setUp(self): self.profile = "facilitydata" self.root_scope_def = ScopeDefinition.objects.create( id="rootcert", profile=self.profile, version=1, primary_scope_param_key="mainpartition", description="Root cert for ${mainpartition}.", read_filter_template="", write_filter_template="", read_write_filter_template="${mainpartition}", ) self.subset_scope_def = ScopeDefinition.objects.create( id="subcert", profile=self.profile, version=1, primary_scope_param_key="", description= "Subset cert under ${mainpartition} for ${subpartition}.", read_filter_template="${mainpartition}", write_filter_template="${mainpartition}:${subpartition}", read_write_filter_template="", ) self.root_cert = Certificate.generate_root_certificate( self.root_scope_def.id) self.subset_cert = Certificate( parent=self.root_cert, profile=self.profile, scope_definition=self.subset_scope_def, scope_version=self.subset_scope_def.version, scope_params=json.dumps({ "mainpartition": self.root_cert.id, "subpartition": "abracadabra" }), private_key=Key(), ) self.root_cert.sign_certificate(self.subset_cert) self.subset_cert.save() self.controller = MorangoProfileController('facilitydata') self.network_connection = self.controller.create_network_connection( '127.0.0.1') @mock_patch_decorator def test_creating_sync_session_successful(self): self.assertEqual(SyncSession.objects.filter(active=True).count(), 0) NetworkSyncConnection._request.return_value.json.return_value = { 'signature': 'sig', 'local_fsic': '{}' } self.network_connection.create_sync_session(self.subset_cert, self.root_cert) self.assertEqual(SyncSession.objects.filter(active=True).count(), 1) @mock_patch_decorator def test_creating_sync_session_cert_fails_to_verify(self): Certificate.verify.return_value = False with self.assertRaises(CertificateSignatureInvalid): self.network_connection.create_sync_session( self.subset_cert, self.root_cert) @mock_patch_decorator def test_get_remote_certs(self): # mock certs being returned by server certs = self.subset_cert.get_ancestors(include_self=True) cert_serialized = json.dumps( CertificateSerializer(certs, many=True).data) NetworkSyncConnection._request.return_value.json.return_value = json.loads( cert_serialized) # we want to see if the models are created (not saved) successfully remote_certs = self.network_connection.get_remote_certificates('abc') self.assertSetEqual(set(certs), set(remote_certs)) @mock_patch_decorator def test_csr(self): # mock a "signed" cert being returned by server cert_serialized = json.dumps( CertificateSerializer(self.subset_cert).data) NetworkSyncConnection._request.return_value.json.return_value = json.loads( cert_serialized) self.subset_cert.delete() # we only want to make sure the "signed" cert is saved with mock.patch.object(Key, "get_private_key_string", return_value=self.subset_cert.private_key. get_private_key_string()): self.network_connection.certificate_signing_request( self.root_cert, '', '') self.assertTrue( Certificate.objects.filter( id=json.loads(cert_serialized)['id']).exists()) @mock_patch_decorator def test_get_cert_chain(self): # mock a cert chain being returned by server certs = self.subset_cert.get_ancestors(include_self=True) original_cert_count = certs.count() cert_serialized = json.dumps( CertificateSerializer(certs, many=True).data) NetworkSyncConnection._request.return_value.json.return_value = json.loads( cert_serialized) Certificate.objects.all().delete() # we only want to make sure the cert chain is saved self.network_connection._get_certificate_chain(certs[1]) self.assertEqual(Certificate.objects.count(), original_cert_count)
class NetworkSyncConnectionTestCase(LiveServerTestCase): def setUp(self): self.profile = "facilitydata" self.root_scope_def = ScopeDefinition.objects.create( id="rootcert", profile=self.profile, version=1, primary_scope_param_key="mainpartition", description="Root cert for ${mainpartition}.", read_filter_template="", write_filter_template="", read_write_filter_template="${mainpartition}", ) self.subset_scope_def = ScopeDefinition.objects.create( id="subcert", profile=self.profile, version=1, primary_scope_param_key="", description= "Subset cert under ${mainpartition} for ${subpartition}.", read_filter_template="${mainpartition}", write_filter_template="${mainpartition}:${subpartition}", read_write_filter_template="", ) self.root_cert = Certificate.generate_root_certificate( self.root_scope_def.id) self.subset_cert = Certificate( parent=self.root_cert, profile=self.profile, scope_definition=self.subset_scope_def, scope_version=self.subset_scope_def.version, scope_params=json.dumps({ "mainpartition": self.root_cert.id, "subpartition": "abracadabra" }), private_key=Key(), ) self.root_cert.sign_certificate(self.subset_cert) self.subset_cert.save() self.unsaved_cert = Certificate( parent=self.root_cert, profile=self.profile, scope_definition=self.subset_scope_def, scope_version=self.subset_scope_def.version, scope_params=json.dumps({ "mainpartition": self.root_cert.id, "subpartition": "other" }), public_key=Key(), ) self.root_cert.sign_certificate(self.unsaved_cert) self.controller = MorangoProfileController('facilitydata') self.network_connection = self.controller.create_network_connection( self.live_server_url) self.key = SharedKey.get_or_create_shared_key() @mock.patch.object(SyncSession.objects, 'create', return_value=None) def test_creating_sync_session_successful(self, mock_object): self.assertEqual(SyncSession.objects.filter(active=True).count(), 0) self.network_connection.create_sync_session(self.subset_cert, self.root_cert) self.assertEqual(SyncSession.objects.filter(active=True).count(), 1) @mock.patch.object(NetworkSyncConnection, '_create_sync_session') @mock.patch.object(Certificate, 'verify', return_value=False) def test_creating_sync_session_cert_fails_to_verify( self, mock_verify, mock_create): mock_create.return_value.json.return_value = {} with self.assertRaises(CertificateSignatureInvalid): self.network_connection.create_sync_session( self.subset_cert, self.root_cert) def test_get_remote_certs(self): certs = self.subset_cert.get_ancestors(include_self=True) remote_certs = self.network_connection.get_remote_certificates( self.root_cert.id) self.assertSetEqual(set(certs), set(remote_certs)) @mock.patch.object(NetworkSyncConnection, '_request') def test_csr(self, mock_request): # mock a "signed" cert being returned by server cert_serialized = json.dumps( CertificateSerializer(self.subset_cert).data) mock_request.return_value.json.return_value = json.loads( cert_serialized) self.subset_cert.delete() # we only want to make sure the "signed" cert is saved with mock.patch.object(Key, "get_private_key_string", return_value=self.subset_cert.private_key. get_private_key_string()): self.network_connection.certificate_signing_request( self.root_cert, '', '') self.assertTrue( Certificate.objects.filter( id=json.loads(cert_serialized)['id']).exists()) @override_settings(ALLOW_CERTIFICATE_PUSHING=True) def test_push_signed_client_certificate_chain(self): cert = self.network_connection.push_signed_client_certificate_chain( self.root_cert, self.subset_scope_def.id, { "mainpartition": self.root_cert.id, "subpartition": "abracadabra" }) self.assertEqual(cert.private_key, None) self.assertTrue(Certificate.objects.filter(id=cert.id).exists()) @override_settings(ALLOW_CERTIFICATE_PUSHING=True) def test_push_signed_client_certificate_chain_publickey_error(self): with mock.patch.object(NetworkSyncConnection, '_get_public_key'): NetworkSyncConnection._get_public_key.return_value.json.return_value = [ { 'public_key': Key().get_public_key_string() } ] with self.assertRaises(HTTPError) as e: self.network_connection.push_signed_client_certificate_chain( self.root_cert, self.subset_scope_def.id, { "mainpartition": self.root_cert.id, "subpartition": "abracadabra" }) self.assertEqual(e.exception.response.status_code, 400) @override_settings(ALLOW_CERTIFICATE_PUSHING=True) def test_push_signed_client_certificate_chain_bad_cert(self): with self.assertRaises(HTTPError) as e: self.network_connection.push_signed_client_certificate_chain( self.root_cert, self.subset_scope_def.id, {"bad": "scope_params"}) self.assertEqual(e.exception.response.status_code, 400) @override_settings(ALLOW_CERTIFICATE_PUSHING=True) @mock.patch.object(NetworkSyncConnection, '_get_nonce') def test_push_signed_client_certificate_chain_nonce_error( self, mock_nonce): mock_nonce.return_value.json.return_value = {'id': uuid.uuid4().hex} with self.assertRaises(HTTPError) as e: self.network_connection.push_signed_client_certificate_chain( self.root_cert, self.subset_scope_def.id, { "mainpartition": self.root_cert.id, "subpartition": "abracadabra" }) self.assertEqual(e.exception.response.status_code, 403) def test_push_signed_client_certificate_chain_not_allowed(self): with self.assertRaises(MorangoServerDoesNotAllowNewCertPush) as e: self.network_connection.push_signed_client_certificate_chain( self.root_cert, self.subset_scope_def.id, { "mainpartition": self.root_cert.id, "subpartition": "abracadabra" }) self.assertEqual(e.exception.response.status_code, 403) def test_get_cert_chain(self): response = self.network_connection._get_certificate_chain( self.subset_cert) data = response.json() self.assertEqual(len(data), Certificate.objects.count()) self.assertEqual(data[0]['id'], self.root_cert.id) self.assertEqual(data[1]['id'], self.subset_cert.id)
class CertificateTestCaseMixin(object): def setUp(self): self.user = MyUser(username="******") self.user.actual_password = "******" self.user.set_password(self.user.actual_password) self.user.save() self.superuser = MyUser(username="******", is_superuser=True) self.superuser.actual_password = "******" self.superuser.set_password(self.superuser.actual_password) self.superuser.save() self.fakeuser = MyUser(username="******") self.fakeuser.actual_password = "******" self.profile = "facilitydata" self.root_scope_def = ScopeDefinition.objects.create( id="rootcert", profile=self.profile, version=1, primary_scope_param_key="mainpartition", description="Root cert for ${mainpartition}.", read_filter_template="", write_filter_template="", read_write_filter_template="${mainpartition}", ) self.subset_scope_def = ScopeDefinition.objects.create( id="subcert", profile=self.profile, version=1, primary_scope_param_key="", description= "Subset cert under ${mainpartition} for ${subpartition}.", read_filter_template= "${mainpartition}:shared\n${mainpartition}:${subpartition}", write_filter_template="${mainpartition}:${subpartition}", read_write_filter_template="", ) self.root_cert1_with_key = Certificate.generate_root_certificate( self.root_scope_def.id) self.subset_cert1_without_key = Certificate( parent=self.root_cert1_with_key, profile=self.profile, scope_definition=self.subset_scope_def, scope_version=self.subset_scope_def.version, scope_params=json.dumps({ "mainpartition": self.root_cert1_with_key.id, "subpartition": "abracadabra" }), private_key=Key(), ) self.root_cert1_with_key.sign_certificate( self.subset_cert1_without_key) self.subset_cert1_without_key.save() self.sub_subset_cert1_with_key = Certificate( parent=self.subset_cert1_without_key, profile=self.profile, scope_definition=self.subset_scope_def, scope_version=self.subset_scope_def.version, scope_params=self.subset_cert1_without_key.scope_params, private_key=Key(), ) self.subset_cert1_without_key.sign_certificate( self.sub_subset_cert1_with_key) self.sub_subset_cert1_with_key.save() self.subset_cert1_without_key._private_key = None self.subset_cert1_without_key.save() self.root_cert2_without_key = Certificate.generate_root_certificate( self.root_scope_def.id) self.subset_cert2_with_key = Certificate( parent=self.root_cert2_without_key, profile=self.profile, scope_definition=self.subset_scope_def, scope_version=self.subset_scope_def.version, scope_params=json.dumps({ "mainpartition": self.root_cert2_without_key.id, "subpartition": "abracadabra" }), private_key=Key(), ) self.root_cert2_without_key.sign_certificate( self.subset_cert2_with_key) self.subset_cert2_with_key.save() self.root_cert2_without_key._private_key = None self.root_cert2_without_key.save() self.original_cert_count = Certificate.objects.count() self.sharedkey = SharedKey.get_or_create_shared_key() # create a root cert self.unsaved_root_cert = Certificate( scope_definition=self.root_scope_def, scope_version=self.root_scope_def.version, profile=self.profile, private_key=Key()) self.unsaved_root_cert.id = self.unsaved_root_cert.calculate_uuid() self.unsaved_root_cert.scope_params = json.dumps({ self.root_scope_def.primary_scope_param_key: self.unsaved_root_cert.id }) self.unsaved_root_cert.sign_certificate(self.unsaved_root_cert) # create a child cert self.unsaved_subset_cert = Certificate( parent=self.unsaved_root_cert, profile=self.profile, scope_definition=self.subset_scope_def, scope_version=self.subset_scope_def.version, scope_params=json.dumps({ "mainpartition": self.unsaved_root_cert.id, "subpartition": "hooplah" }), public_key=self.sharedkey.public_key, ) def make_cert_endpoint_request(self, params={}, method="GET"): fn = getattr(self.client, method.lower()) response = fn(reverse('certificates-list'), params, format='json') data = json.loads(response.content.decode()) return (response, data) def perform_basic_authentication(self, user): basic_auth_header = b'Basic ' + base64.encodestring( ("username=%s:%s" % (user.username, user.actual_password)).encode()) self.client.credentials(HTTP_AUTHORIZATION=basic_auth_header) def create_syncsession(self, client_certificate=None, server_certificate=None): if not client_certificate: client_certificate = self.sub_subset_cert1_with_key if not server_certificate: server_certificate = self.root_cert1_with_key # fetch a nonce value to use in creating the syncsession response = self.client.post(reverse('nonces-list'), {}, format='json') nonce = json.loads(response.content.decode())["id"] # prepare the data to send in the syncsession creation request data = { "id": uuid.uuid4().hex, "server_certificate_id": server_certificate.id, "client_certificate_id": client_certificate.id, "profile": client_certificate.profile, "certificate_chain": json.dumps( CertificateSerializer( client_certificate.get_ancestors(include_self=True), many=True).data), "connection_path": "http://127.0.0.1:8000", "instance": json.dumps( InstanceIDSerializer( InstanceIDModel.get_or_create_current_instance()[0]).data), "nonce": nonce, } # sign the nonce/ID combo to attach to the request data["signature"] = client_certificate.sign( "{nonce}:{id}".format(**data)) # make the API call to create the SyncSession response = self.client.post(reverse('syncsessions-list'), data, format='json') self.assertEqual(response.status_code, 201) return SyncSession.objects.get(id=data["id"]) def make_transfersession_creation_request(self, filter, push, syncsession=None, expected_status=201, expected_message=None, **kwargs): if not syncsession: syncsession = self.create_syncsession() data = { "id": uuid.uuid4().hex, "filter": filter, "push": push, "records_total": 0, "sync_session_id": syncsession.id, } # make the API call to attempt to create the TransferSession response = self.client.post(reverse('transfersessions-list'), data, format='json') self.assertEqual(response.status_code, expected_status) if expected_status == 201: # check that the syncsession was created transfersession = TransferSession.objects.get( id=json.loads(response.content.decode())["id"]) self.assertTrue(transfersession.active) else: # check that the syncsession was not created self.assertEqual(TransferSession.objects.count(), 0) if expected_message: self.assertIn(expected_message, response.content.decode()) return response