use of com.quorum.tessera.partyinfo.model.PartyInfo in project tessera by ConsenSys.
the class PartyInfoResourceTest method partyInfo.
@Test
public void partyInfo() {
String url = "http://www.bogus.com";
PublicKey myKey = PublicKey.from("myKey".getBytes());
PublicKey recipientKey = PublicKey.from("recipientKey".getBytes());
String message = "I love sparrows";
byte[] payload = message.getBytes();
Recipient recipient = Recipient.of(recipientKey, url);
Set<Recipient> recipientList = Collections.singleton(recipient);
PartyInfo partyInfo = new PartyInfo(url, recipientList, Collections.emptySet());
when(partyInfoParser.from(payload)).thenReturn(partyInfo);
when(enclave.defaultPublicKey()).thenReturn(myKey);
when(partyInfoParser.to(partyInfo)).thenReturn(payload);
EncodedPayload encodedPayload = mock(EncodedPayload.class);
List<String> uuidList = new ArrayList<>();
doAnswer((invocation) -> {
byte[] d = invocation.getArgument(0);
uuidList.add(new String(d));
return encodedPayload;
}).when(enclave).encryptPayload(any(byte[].class), any(PublicKey.class), anyList(), any(PrivacyMetadata.class));
when(payloadEncoder.encode(encodedPayload)).thenReturn(payload);
WebTarget webTarget = mock(WebTarget.class);
when(restClient.target(url)).thenReturn(webTarget);
when(webTarget.path(anyString())).thenReturn(webTarget);
Invocation.Builder invocationBuilder = mock(Invocation.Builder.class);
when(webTarget.request()).thenReturn(invocationBuilder);
Response response = mock(Response.class);
when(response.getStatus()).thenReturn(200);
doAnswer((invocation) -> uuidList.get(0)).when(response).readEntity(String.class);
when(invocationBuilder.post(any(Entity.class))).thenReturn(response);
Response result = partyInfoResource.partyInfo(payload, List.of("v1,v2"));
assertThat(result.getStatus()).isEqualTo(200);
verify(partyInfoParser).from(payload);
verify(enclave).defaultPublicKey();
verify(enclave).encryptPayload(any(byte[].class), any(PublicKey.class), anyList(), any(PrivacyMetadata.class));
verify(payloadEncoder).encode(encodedPayload);
verify(restClient).target(url);
ArgumentCaptor<NodeInfo> argCaptor = ArgumentCaptor.forClass(NodeInfo.class);
verify(discovery).onUpdate(argCaptor.capture());
final NodeInfo nodeInfo = argCaptor.getValue();
assertThat(nodeInfo).isNotNull();
assertThat(nodeInfo.getUrl()).isEqualTo(url);
assertThat(nodeInfo.supportedApiVersions()).containsExactlyInAnyOrder("v1", "v2");
}
use of com.quorum.tessera.partyinfo.model.PartyInfo in project tessera by ConsenSys.
the class PartyInfoResourceTest method partyInfoExceptionIfValidationFailsWith200.
@Test
public void partyInfoExceptionIfValidationFailsWith200() {
final int validateResponseCode = 200;
final String validateResponseMsg = "BADRESPONSE";
String url = "http://www.bogus.com";
PublicKey myKey = PublicKey.from("myKey".getBytes());
PublicKey recipientKey = PublicKey.from("recipientKey".getBytes());
String message = "I love sparrows";
byte[] payload = message.getBytes();
Recipient recipient = Recipient.of(recipientKey, url);
Set<Recipient> recipientList = Collections.singleton(recipient);
PartyInfo partyInfo = new PartyInfo(url, recipientList, Collections.emptySet());
when(partyInfoParser.from(payload)).thenReturn(partyInfo);
when(enclave.defaultPublicKey()).thenReturn(myKey);
when(partyInfoParser.to(partyInfo)).thenReturn(payload);
EncodedPayload encodedPayload = mock(EncodedPayload.class);
when(enclave.encryptPayload(any(byte[].class), any(PublicKey.class), anyList(), any(PrivacyMetadata.class))).thenReturn(encodedPayload);
when(payloadEncoder.encode(encodedPayload)).thenReturn(payload);
WebTarget webTarget = mock(WebTarget.class);
when(restClient.target(url)).thenReturn(webTarget);
when(webTarget.path(anyString())).thenReturn(webTarget);
Invocation.Builder invocationBuilder = mock(Invocation.Builder.class);
when(webTarget.request()).thenReturn(invocationBuilder);
Response response = mock(Response.class);
when(response.getStatus()).thenReturn(validateResponseCode);
doAnswer((invocation) -> validateResponseMsg).when(response).readEntity(String.class);
when(invocationBuilder.post(any(Entity.class))).thenReturn(response);
try {
partyInfoResource.partyInfo(payload, Collections.emptyList());
failBecauseExceptionWasNotThrown(SecurityException.class);
} catch (SecurityException ex) {
verify(partyInfoParser).from(payload);
verify(enclave).defaultPublicKey();
verify(enclave).encryptPayload(any(byte[].class), any(PublicKey.class), anyList(), any(PrivacyMetadata.class));
verify(payloadEncoder).encode(encodedPayload);
verify(restClient).target(url);
}
}
use of com.quorum.tessera.partyinfo.model.PartyInfo in project tessera by ConsenSys.
the class PartyInfoBroadcasterTest method exceptionThrowByPostDoesntBubble.
@Test
public void exceptionThrowByPostDoesntBubble() {
final NodeInfo partyInfo = NodeInfo.Builder.create().withUrl(OWN_URL).build();
when(partyStore.getParties()).thenReturn(Set.of(URI.create(TARGET_URL), URI.create(TARGET_URL_2)));
doReturn(partyInfo).when(discovery).getCurrent();
doThrow(UnsupportedOperationException.class).when(p2pClient).sendPartyInfo(TARGET_URL, DATA);
final Throwable throwable = catchThrowable(partyInfoBroadcaster::run);
assertThat(throwable).isNull();
verify(partyStore).loadFromConfigIfEmpty();
verify(partyStore).getParties();
verify(p2pClient).sendPartyInfo(TARGET_URL, DATA);
verify(p2pClient).sendPartyInfo(TARGET_URL_2, DATA);
verify(discovery).getCurrent();
verify(partyInfoParser).to(any(PartyInfo.class));
}
use of com.quorum.tessera.partyinfo.model.PartyInfo in project tessera by ConsenSys.
the class PartyInfoBroadcaster method run.
/**
* Iterates over all known parties and contacts them for the current state of their known node
* discovery list
*
* <p>For Tessera 0.9 backwards, after contacting the known parties, this poller then updates this
* nodes list of data with any new information collected.
*
* <p>This behaviour is now deprecated since the /partyinfo API call now has been made more strict
* with node validation to prevent exploiting the API to attack the Tessera network.
*
* <p>This call is merely to let its parties know about this node existence, any recipients that
* want to be added to this node's PartyInfo will need to make their own partyinfo call and
* validation
*/
@Override
public void run() {
LOGGER.info("Started PartyInfo polling round");
partyStore.loadFromConfigIfEmpty();
final NodeInfo nodeInfo = discovery.getCurrent();
final NodeUri ourUrl = NodeUri.create(nodeInfo.getUrl());
final PartyInfo partyInfo = PartyInfoBuilder.create().withUri(nodeInfo.getUrl()).withRecipients(nodeInfo.getRecipientsAsMap()).build();
final byte[] encodedPartyInfo = partyInfoParser.to(partyInfo);
LOGGER.debug("Contacting following peers with PartyInfo: {}", partyInfo.getParties());
LOGGER.debug("Sending party info {}", nodeInfo);
partyStore.getParties().stream().map(NodeUri::create).filter(url -> !ourUrl.equals(url)).forEach(url -> pollSingleParty(url.asString(), encodedPartyInfo));
LOGGER.info("Finished PartyInfo polling round");
}
use of com.quorum.tessera.partyinfo.model.PartyInfo in project tessera by ConsenSys.
the class SyncPoller method updatePartyInfo.
private boolean updatePartyInfo(String url) {
try {
final NodeInfo nodeInfo = discovery.getCurrent();
final PartyInfo partyInfo = PartyInfoBuilder.create().withUri(nodeInfo.getUrl()).withRecipients(nodeInfo.getRecipientsAsMap()).build();
LOGGER.debug("Sending node info {} to {}", nodeInfo, url);
final byte[] encodedPartyInfo = partyInfoParser.to(partyInfo);
// we deliberately discard the response as we do not want to fully duplicate the
// PartyInfoPoller
boolean outcome = p2pClient.sendPartyInfo(url, encodedPartyInfo);
LOGGER.debug("Sent node info {} to {}", nodeInfo, url);
return outcome;
} catch (final Exception ex) {
LOGGER.warn("Failed to connect to node {} for partyinfo, due to {}", url, ex.getMessage());
LOGGER.debug(null, ex);
return false;
}
}
Aggregations