fix(java-client): redact operator password on async acknowledge-alarm failures
Claude-Session: https://claude.ai/code/session_016J6isfcgqy4SB2RK3ZvFvT
This commit is contained in:
+15
-1
@@ -308,10 +308,24 @@ public final class MxGatewayClient implements AutoCloseable {
|
||||
*/
|
||||
public CompletableFuture<AcknowledgeAlarmReply> acknowledgeAlarmAsync(AcknowledgeAlarmRequest request) {
|
||||
CompletableFuture<AcknowledgeAlarmReply> future = toCompletable(rawFutureStub().acknowledgeAlarm(request));
|
||||
return future.thenApply(reply -> {
|
||||
String secret = request.getOperatorPassword();
|
||||
CompletableFuture<AcknowledgeAlarmReply> checked = future.thenApply(reply -> {
|
||||
MxGatewayErrors.ensureProtocolSuccess("acknowledge alarm", reply.getProtocolStatus(), null);
|
||||
return reply;
|
||||
});
|
||||
if (secret.isEmpty()) {
|
||||
return checked;
|
||||
}
|
||||
// Scrub the operator password from any failure surfaced through the future.
|
||||
return checked.exceptionally(error -> {
|
||||
Throwable cause = error instanceof java.util.concurrent.CompletionException && error.getCause() != null
|
||||
? error.getCause()
|
||||
: error;
|
||||
if (cause instanceof MxGatewayException gatewayError) {
|
||||
throw new java.util.concurrent.CompletionException(MxGatewayErrors.redacted(gatewayError, secret));
|
||||
}
|
||||
throw new java.util.concurrent.CompletionException(cause);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+46
@@ -74,6 +74,52 @@ final class MxGatewayCredentialReplyTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void acknowledgeAlarmAsyncRedactsOperatorPasswordFromFailure() throws Exception {
|
||||
String serverName = "mxgw-java-ack-" + UUID.randomUUID();
|
||||
MxAccessGatewayGrpc.MxAccessGatewayImplBase service = new MxAccessGatewayGrpc.MxAccessGatewayImplBase() {
|
||||
@Override
|
||||
public void acknowledgeAlarm(
|
||||
mxaccess_gateway.v1.MxaccessGateway.AcknowledgeAlarmRequest request,
|
||||
StreamObserver<mxaccess_gateway.v1.MxaccessGateway.AcknowledgeAlarmReply> observer) {
|
||||
observer.onNext(mxaccess_gateway.v1.MxaccessGateway.AcknowledgeAlarmReply.newBuilder()
|
||||
.setProtocolStatus(ProtocolStatus.newBuilder()
|
||||
.setCode(ProtocolStatusCode.PROTOCOL_STATUS_CODE_MXACCESS_FAILURE)
|
||||
.setMessage("auth failed for operator1 password " + CREDENTIAL))
|
||||
.build());
|
||||
observer.onCompleted();
|
||||
}
|
||||
};
|
||||
Server server = InProcessServerBuilder.forName(serverName)
|
||||
.directExecutor().addService(service).build().start();
|
||||
ManagedChannel channel = InProcessChannelBuilder.forName(serverName).directExecutor().build();
|
||||
try (MxGatewayClient client = new MxGatewayClient(
|
||||
channel,
|
||||
MxGatewayClientOptions.builder()
|
||||
.endpoint("in-process").apiKey("").plaintext(true)
|
||||
.callTimeout(Duration.ofSeconds(5)).build())) {
|
||||
var request = mxaccess_gateway.v1.MxaccessGateway.AcknowledgeAlarmRequest.newBuilder()
|
||||
.setAlarmFullReference("Tank01.Level.HiHi")
|
||||
.setOperatorUser("operator1")
|
||||
.setOperatorPassword(CREDENTIAL)
|
||||
.build();
|
||||
|
||||
java.util.concurrent.ExecutionException async = assertThrows(
|
||||
java.util.concurrent.ExecutionException.class,
|
||||
() -> client.acknowledgeAlarmAsync(request).get());
|
||||
assertTrue(async.getCause() instanceof MxGatewayException, String.valueOf(async.getCause()));
|
||||
assertFalse(async.getCause().getMessage().contains(CREDENTIAL));
|
||||
assertFalse(((MxGatewayCommandException) async.getCause()).protocolStatus().getMessage()
|
||||
.contains(CREDENTIAL));
|
||||
|
||||
MxGatewayException sync = assertThrows(MxGatewayException.class, () -> client.acknowledgeAlarm(request));
|
||||
assertFalse(sync.getMessage().contains(CREDENTIAL));
|
||||
} finally {
|
||||
channel.shutdownNow();
|
||||
server.shutdownNow();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void authenticateUserMissingPayloadThrowsMalformedReply() throws Exception {
|
||||
MxCommandReply reply = loadReply("authenticate-user.missing-payload.reply.json");
|
||||
|
||||
Reference in New Issue
Block a user