Exemplo n.º 1
0
    def certificate_signing_request(self,
                                    parent_cert,
                                    scope_definition_id,
                                    scope_params,
                                    userargs=None,
                                    password=None):
        # if server cert does not exist locally, retrieve it from server
        if not Certificate.objects.filter(id=parent_cert.id).exists():
            cert_chain_response = self._get_certificate_chain(parent_cert)

            # upon receiving cert chain from server, we attempt to save the chain into our records
            Certificate.save_certificate_chain(cert_chain_response.json(),
                                               expected_last_id=parent_cert.id)

        csr_key = Key()
        # build up data for csr
        data = {
            "parent": parent_cert.id,
            "profile": parent_cert.profile,
            "scope_definition": scope_definition_id,
            "scope_version": parent_cert.scope_version,
            "scope_params": json.dumps(scope_params),
            "public_key": csr_key.get_public_key_string()
        }
        csr_resp = self._request(api_urls.CERTIFICATE,
                                 method="POST",
                                 data=data,
                                 userargs=userargs,
                                 password=password)
        csr_data = csr_resp.json()

        # verify cert returned from server, and proceed to save into our records
        csr_cert = Certificate.deserialize(csr_data["serialized"],
                                           csr_data["signature"])
        csr_cert.private_key = csr_key
        csr_cert.check_certificate()
        csr_cert.save()
        return csr_cert
Exemplo n.º 2
0
    def _get_certificate_chain(self, server_cert):
        # get ancestors certificate chain for this server cert
        cert_chain_resp = self._request(api_urls.CERTIFICATE, params={'ancestors_of': server_cert.id})

        # upon receiving cert chain from server, we attempt to save the chain into our records
        Certificate.save_certificate_chain(cert_chain_resp.json(), expected_last_id=server_cert.id)
Exemplo n.º 3
0
    def create_sync_session(self, client_cert, server_cert):
        # if server cert does not exist locally, retrieve it from server
        if not Certificate.objects.filter(id=server_cert.id).exists():
            cert_chain_response = self._get_certificate_chain(server_cert)

            # upon receiving cert chain from server, we attempt to save the chain into our records
            Certificate.save_certificate_chain(cert_chain_response.json(),
                                               expected_last_id=server_cert.id)

        # request the server for a one-time-use nonce
        nonce_resp = self._get_nonce()
        nonce = json.loads(nonce_resp.content.decode())["id"]

        # if no hostname then url is actually an ip
        url = urlparse(self.base_url)
        hostname = url.hostname or self.base_url
        port = url.port or (80 if url.scheme == 'http' else 443)

        # prepare the data to send in the syncsession creation request
        data = {
            "id":
            uuid.uuid4().hex,
            "server_certificate_id":
            server_cert.id,
            "client_certificate_id":
            client_cert.id,
            "profile":
            client_cert.profile,
            "certificate_chain":
            json.dumps(
                CertificateSerializer(
                    client_cert.get_ancestors(include_self=True),
                    many=True).data),
            "connection_path":
            self.base_url,
            "instance":
            json.dumps(
                InstanceIDSerializer(
                    InstanceIDModel.get_or_create_current_instance()[0]).data),
            "nonce":
            nonce,
            "client_ip":
            _get_client_ip_for_server(hostname, port),
            "server_ip":
            _get_server_ip(hostname),
        }

        # sign the nonce/ID combo to attach to the request
        message = "{nonce}:{id}".format(**data)
        data["signature"] = client_cert.sign(message)

        # Sync Session creation request
        session_resp = self._create_sync_session(data)

        # check that the nonce/id were properly signed by the server cert
        if not server_cert.verify(message,
                                  session_resp.json().get("signature")):
            raise CertificateSignatureInvalid()

        # build the data to be used for creating our own syncsession
        data = {
            "id":
            data['id'],
            "start_timestamp":
            timezone.now(),
            "last_activity_timestamp":
            timezone.now(),
            "active":
            True,
            "is_server":
            False,
            "client_certificate":
            client_cert,
            "server_certificate":
            server_cert,
            "profile":
            client_cert.profile,
            "connection_kind":
            "network",
            "connection_path":
            self.base_url,
            "client_ip":
            data['client_ip'],
            "server_ip":
            data['server_ip'],
            "client_instance":
            json.dumps(
                InstanceIDSerializer(
                    InstanceIDModel.get_or_create_current_instance()[0]).data),
            "server_instance":
            session_resp.json().get("server_instance") or "{}",
        }
        sync_session = SyncSession.objects.create(**data)

        return SyncClient(self, sync_session)