Пример #1
0
    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()
Пример #2
0
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()
Пример #3
0
    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
Пример #4
0
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)
Пример #5
0
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)
Пример #6
0
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