Commit 9da1b7b1 authored by Georg Mittendorfer's avatar Georg Mittendorfer

Change logging in case of invalid and/or unauthorized requests.

parent 0cfa037a
......@@ -35,6 +35,7 @@ import io.micrometer.core.instrument.Counter;
import io.vavr.Tuple;
import io.vavr.Tuple2;
import io.vavr.collection.List;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -192,6 +193,7 @@ public class IriApiHandler {
private Mono<ResponseEntity<String>> unauthorized(IriCommand command) {
rejectedCommandCounter(command.getCommand()).increment();
logger.debug("Rejecting unauthorized command [{}] from IP [{}]", command.getCommand(), command.getIp());
return Mono.just(createUnauthorizedResponse(command));
}
......@@ -205,19 +207,23 @@ public class IriApiHandler {
@ExceptionHandler(WebExchangeBindException.class)
public ResponseEntity handleInvalidCommand(WebExchangeBindException wex) {
rejectedCommandCounter("invalid").increment();
String errorMessage = ExceptionHandlerUtil.extractValidationErrorMessage(wex);
if (wex.getTarget() instanceof IriCommand && !commandChecker.isEnabled((IriCommand) wex.getTarget())) {
// return unauthorized as IRI does
logger.info("Received unauthorized and invalid [{}] request: {}.", ((IriCommand) wex.getTarget()).getCommand(), errorMessage);
String errorMessage = ExceptionHandlerUtil.extractValidationErrorMessage(wex);
String validationTarget = logger.isDebugEnabled()
? String.valueOf(wex.getTarget())
: StringUtils.abbreviate(String.valueOf(wex.getTarget()), 116);
logger.info("Validation failure: [{}]", validationTarget);
logger.info(errorMessage);
if (isUnauthorizedIriCommand(wex.getTarget())) {
// return unauthorized instead of bad request like IRI does it
logger.debug("Received invalid unauthorized [{}] request. Returning 401...", ((IriCommand) wex.getTarget()).getCommand());
return createUnauthorizedResponse((IriCommand) wex.getTarget());
} else if (wex.getTarget() instanceof AttachToTangle) {
} else if (isEmptyAttachToTangle(wex.getTarget())) {
logger.debug("Received empty AttachToTangle. Returning POW enabled response (400)...");
// exactly this response is needed for pow check
logger.debug("Received POW check. Returned POW enabled response.");
return invalidCommandResponse();
} else {
logger.info("Validation failure: [{}]", StringUtils.abbreviate(String.valueOf(wex.getTarget()), 116));
logger.info(errorMessage);
// this is not 100% compatible with IRI as the error message is much more detailed. If this
// is a problem change to invalidCommandResponse
throw ExceptionHandlerUtil.convertToResponseException(wex, errorMessage);
......@@ -236,13 +242,18 @@ public class IriApiHandler {
binder.addValidators(commandValidator);
}
private Counter rejectedCommandCounter(String command) {
return rejectedCommandsCounter.computeIfAbsent(command, key -> metrics.createRejectedCommandCounter(command));
private boolean isUnauthorizedIriCommand(Object input) {
return input instanceof IriCommand && !commandChecker.isEnabled((IriCommand) input);
}
private Counter failedCommandCounter(String command, Throwable throwable) {
String error = throwable.getClass().getSimpleName();
return failedCommandsCounter.computeIfAbsent(Tuple.of(command, error), key -> metrics.createFailedCommandCounter(command, error));
private boolean isEmptyAttachToTangle(Object input) {
if (input instanceof AttachToTangle) {
AttachToTangle att = (AttachToTangle) input;
return StringUtils.isAllEmpty(att.getTrunkTransaction(), att.getBranchTransaction())
&& CollectionUtils.isEmpty(att.getTrytes());
} else {
return false;
}
}
private ResponseEntity<String> invalidCommandResponse() {
......@@ -258,4 +269,13 @@ public class IriApiHandler {
.body("{\"error\":\"COMMAND " + command.getCommand() + " is not available on this node\",\"duration\":0}");
}
private Counter rejectedCommandCounter(String command) {
return rejectedCommandsCounter.computeIfAbsent(command, key -> metrics.createRejectedCommandCounter(command));
}
private Counter failedCommandCounter(String command, Throwable throwable) {
String error = throwable.getClass().getSimpleName();
return failedCommandsCounter.computeIfAbsent(Tuple.of(command, error), key -> metrics.createFailedCommandCounter(command, error));
}
}
......@@ -189,7 +189,7 @@ public class NodesApiHandlerIT {
@Test
public void givenInvalidLengthWhenRegisterThen400() {
EntityExchangeResult<String> result = registerNode(new RegisterNodeRequest("1234567890123456789012345678901234567890", "http://localhost:1234", true))
EntityExchangeResult<String> result = registerNode(new RegisterNodeRequest("1234567890123456789012345678901234567890123", "http://localhost:1234", true))
.expectStatus().isBadRequest()
.expectBody(String.class).returnResult();
logger.debug("Result: {} => {}", result.getStatus(), result.getResponseBody());
......
......@@ -253,8 +253,9 @@ public class IriApiHandlerCommandsSysIT {
assertThat(result).contains("{\"error\":\"Invalid parameters\",\"duration\":");
}
// behaviour is not 100 percent compatible to IRI as it returns {"error":"Invalid parameters","duration":"...
@Test
public void givenInvalidWeightWhenAttachToTangleThenSimulateIriBehaviour() {
public void givenInvalidWeightWhenAttachToTangleThenDoNotSimulateIriBehaviourButReturnValidationErrors() {
AttachToTangle att = attachToTangleCommand("foo", "bar", "foobar");
att.setMinWeightMagnitude(1);
String result = util.postCommand(att)
......@@ -262,7 +263,8 @@ public class IriApiHandlerCommandsSysIT {
.isBadRequest()
.expectBody(String.class).returnResult().getResponseBody();
logger.info(result);
assertThat(result).contains("{\"error\":\"Invalid parameters\",\"duration\":");
assertThat(result).contains("\"error\":\"Bad Request");
assertThat(result).contains("\"message\":\"Validation failure");
}
private <T> T postCommandExpectOk(Object command, Class<T> responseClass) {
......
......@@ -56,7 +56,7 @@ public class TestCommandFactory {
att.setTrunkTransaction(trunk);
att.setBranchTransaction(branch);
att.setMinWeightMagnitude(14); // min allowed value for mainnet is 14. min value for testnet is 9.
att.setTrytes(Collections.singletonList(trytes));
att.setTrytes(trytes == null ? null : Collections.singletonList(trytes));
return att;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment