Refactor to use new RevocationKit

pull/521/head
tuxxy 2018-11-15 00:42:06 -07:00
parent 88054ecc8f
commit 0ddfa230de
5 changed files with 58 additions and 22 deletions

View File

@ -170,22 +170,27 @@ class Alice(Character, PolicyAuthor):
Parses the treasure map and revokes arrangements in it.
If any arrangements can't be revoked (other than a 404 status), then
the node_id and arrangement_id are added to a list and returned.
TODO: How do we tell the user that a revocation was successful or not?
"""
failed_revocations = list()
for node_id, arrangement_id in policy.treasure_map:
# TODO: What about nodes we don't know about?
ursula = self._known_nodes[node_id]
try:
self.network_middleware.revoke_arrangement(ursula, arrangement_id)
except RuntimeError as e:
# Check the status code of the response to determine what to do
# TODO: What do we do in the event of a 404? Is there are way
# to check if it's a real 404 and not SuspiciousActivity?
if e[1] != 404:
failed_revocations.append((node_id, arrangement_id))
continue
# Sign the revocations in the RevocationKit in preparation for
# sending to Ursula.
policy.revocation_kit.sign_revocations(self.stamp)
try:
# Wait for a revocation threshold of nodes to be known ((n - m) + 1)
revocation_threshold = ((policy.n - policy.treasure_map.m) + 1)
self.block_until_specific_nodes_are_known(
policy.revocation_kit.revokable_addresses,
allow_missing=revocation_threshold)
except self.NotEnoughTeachers as e:
raise e
else:
failed_revocations = list()
for node_id in policy.revocation_kit.revokable_addresses:
ursula = self.known_nodes[node_id]
revocation = policy.revocation_kit[node_id]
response = self.network_middleware.revoke_arrangement(ursula, revocation)
if response.status_code != 200:
failed_revocations.append(notice)
return failed_revocations

View File

@ -261,15 +261,27 @@ class ProxyRESTRoutes:
TODO: How do we want to verify that this request comes from Alice?
What/How is she going to sign?
"""
arrangement_id = request.body
from nucypher.crypto.kits import RevocationKit
revocation = RevocationKit.revocation_from_bytes(request.body)
try:
with ThreadedSession(self.db_engine) as session:
self.datastore.del_policy_arrangement(
arrangement_id,
session=session)
except NotFound:
return 404 # TODO: Should we 404 or do something else?
return 200
# Verify the Notice was signed by Alice
policy_arrangement = self.datastore.get_policy_arrangement(
id_as_hex.encode(), session=session)
alice_pubkey = UmbralPublicKey.from_bytes(
policy_arrangement.alice_pubkey_sig.key_data)
# Check that the request is the same for the provided revocation
if not id_as_hex.encode() == revocation.arrangement_id:
return 400
elif RevocationKit.verify_revocation(revocation, alice_pubkey):
self.datastore.del_policy_arrangement(
id_as_hex.encode(), session=session)
except (NotFound, InvalidSignature):
return 404
else:
return 200
def reencrypt_via_rest(self, id_as_hex, request: http.Request):
from nucypher.policy.models import WorkOrder # Avoid circular import

View File

@ -248,6 +248,9 @@ class Policy:
self.treasure_map.add_arrangement(arrangement)
else: # ...After *all* the policies are enacted
# Create Alice's revocation kit
self.revocation_kit = RevocationKit(self.treasure_map)
if publish is True:
return self.publish(network_middleware)

View File

@ -14,9 +14,12 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
from apistar import TestClient
from nucypher.characters.lawful import Ursula
from nucypher.crypto.kits import RevocationKit
from nucypher.network.middleware import RestMiddleware
from nucypher.utilities.sandbox.constants import TEST_KNOWN_URSULAS_CACHE
@ -107,6 +110,18 @@ class MockRestMiddleware(RestMiddleware):
data=map_payload, verify=certificate_filepath)
return response
def revoke_arrangement(self, ursula, revocation):
mock_client = self._get_mock_client_by_ursula(ursula)
response = mock_client.delete('http://localhost/kFrag/{}'.format(
revocation.arrangement_id.hex()),
data=RevocationKit.revocation_to_bytes(revocation))
if response.status_code != 200:
if response.status_code == 404:
raise RuntimeError("KFrag doesn't exist to revoke with id {}".format(arrangement_id))
raise RuntimeError("Bad response: {}".format(response.status_code))
return response
class EvilMiddleWare(MockRestMiddleware):
"""

View File

@ -27,6 +27,7 @@ from nucypher.characters.lawful import Bob, Ursula
from nucypher.config.characters import AliceConfiguration
from nucypher.config.storages import LocalFileBasedNodeStorage
from nucypher.crypto.api import keccak_digest
from nucypher.crypto.kits import RevocationKit
from nucypher.crypto.powers import SigningPower, DelegatingPower, EncryptingPower
from nucypher.utilities.sandbox.constants import TEST_URSULA_INSECURE_DEVELOPMENT_PASSWORD
from nucypher.utilities.sandbox.middleware import MockRestMiddleware