use of org.eclipse.hono.auth.HonoUser in project hono by eclipse.
the class AmqpServiceBase method handleSenderOpen.
/**
* Handles a request from a client to establish a link for receiving messages from this server.
*
* @param con the connection to the client.
* @param sender the sender created for the link.
*/
protected void handleSenderOpen(final ProtonConnection con, final ProtonSender sender) {
final Source remoteSource = sender.getRemoteSource();
LOG.debug("client [container: {}] wants to open a link [address: {}] for receiving messages", con.getRemoteContainer(), remoteSource);
try {
final ResourceIdentifier targetResource = getResourceIdentifier(remoteSource.getAddress());
final AmqpEndpoint endpoint = getEndpoint(targetResource);
if (endpoint == null) {
handleUnknownEndpoint(con, sender, targetResource);
} else {
final HonoUser user = Constants.getClientPrincipal(con);
getAuthorizationService().isAuthorized(user, targetResource, Activity.READ).setHandler(authAttempt -> {
if (authAttempt.succeeded() && authAttempt.result()) {
Constants.copyProperties(con, sender);
sender.setSource(sender.getRemoteSource());
endpoint.onLinkAttach(con, sender, targetResource);
} else {
LOG.debug("subject [{}] is not authorized to READ from [{}]", user.getName(), targetResource);
sender.setCondition(ProtonHelper.condition(AmqpError.UNAUTHORIZED_ACCESS.toString(), "unauthorized"));
sender.close();
}
});
}
} catch (final IllegalArgumentException e) {
LOG.debug("client has provided invalid resource identifier as target address", e);
sender.setCondition(ProtonHelper.condition(AmqpError.NOT_FOUND, "no such address"));
sender.close();
}
}
use of org.eclipse.hono.auth.HonoUser in project hono by eclipse.
the class AmqpServiceBase method handleReceiverOpen.
/**
* Handles a request from a client to establish a link for sending messages to this server.
* The already established connection must have an authenticated user as principal for doing the authorization check.
*
* @param con the connection to the client.
* @param receiver the receiver created for the link.
*/
protected void handleReceiverOpen(final ProtonConnection con, final ProtonReceiver receiver) {
if (receiver.getRemoteTarget().getAddress() == null) {
LOG.debug("client [container: {}] wants to open an anonymous link for sending messages to arbitrary addresses, closing link ...", con.getRemoteContainer());
receiver.setCondition(ProtonHelper.condition(AmqpError.NOT_ALLOWED, "anonymous relay not supported"));
receiver.close();
} else {
LOG.debug("client [container: {}] wants to open a link [address: {}] for sending messages", con.getRemoteContainer(), receiver.getRemoteTarget());
try {
final ResourceIdentifier targetResource = getResourceIdentifier(receiver.getRemoteTarget().getAddress());
final AmqpEndpoint endpoint = getEndpoint(targetResource);
if (endpoint == null) {
handleUnknownEndpoint(con, receiver, targetResource);
} else {
final HonoUser user = Constants.getClientPrincipal(con);
getAuthorizationService().isAuthorized(user, targetResource, Activity.WRITE).setHandler(authAttempt -> {
if (authAttempt.succeeded() && authAttempt.result()) {
Constants.copyProperties(con, receiver);
receiver.setTarget(receiver.getRemoteTarget());
endpoint.onLinkAttach(con, receiver, targetResource);
} else {
LOG.debug("subject [{}] is not authorized to WRITE to [{}]", user.getName(), targetResource);
receiver.setCondition(ProtonHelper.condition(AmqpError.UNAUTHORIZED_ACCESS.toString(), "unauthorized"));
receiver.close();
}
});
}
} catch (final IllegalArgumentException e) {
LOG.debug("client has provided invalid resource identifier as target address", e);
receiver.setCondition(ProtonHelper.condition(AmqpError.NOT_FOUND, "no such address"));
receiver.close();
}
}
}
use of org.eclipse.hono.auth.HonoUser in project hono by eclipse.
the class RequestResponseEndpoint method handleMessage.
/**
* Handles a request message received from a client.
* <p>
* The message gets rejected if
* <ul>
* <li>the message does not pass {@linkplain #passesFormalVerification(ResourceIdentifier, Message) formal verification}
* or</li>
* <li>the client is not {@linkplain #isAuthorized(HonoUser, ResourceIdentifier, Message) authorized to execute the operation}
* indicated by the message's <em>subject</em> or</li>
* <li>its payload cannot be parsed</li>
* </ul>
*
* @param con The connection with the client.
* @param receiver The link over which the message has been received.
* @param targetAddress The address the message is sent to.
* @param delivery The message's delivery status.
* @param message The message.
*/
protected final void handleMessage(final ProtonConnection con, final ProtonReceiver receiver, final ResourceIdentifier targetAddress, ProtonDelivery delivery, Message message) {
final Future<Void> formalCheck = Future.future();
if (passesFormalVerification(targetAddress, message)) {
formalCheck.complete();
} else {
formalCheck.fail(new AmqpErrorException(AmqpError.DECODE_ERROR, "malformed payload"));
}
final HonoUser clientPrincipal = Constants.getClientPrincipal(con);
formalCheck.compose(ok -> isAuthorized(clientPrincipal, targetAddress, message)).compose(authorized -> {
logger.debug("client [{}] is {}authorized to {}:{}", clientPrincipal.getName(), authorized ? "" : "not ", targetAddress, message.getSubject());
if (authorized) {
try {
processRequest(message, targetAddress, clientPrincipal);
ProtonHelper.accepted(delivery, true);
return Future.succeededFuture();
} catch (DecodeException e) {
return Future.failedFuture(new AmqpErrorException(AmqpError.DECODE_ERROR, "malformed payload"));
}
} else {
return Future.failedFuture(new AmqpErrorException(AmqpError.UNAUTHORIZED_ACCESS, "unauthorized"));
}
}).otherwise(t -> {
if (t instanceof AmqpErrorException) {
AmqpErrorException cause = (AmqpErrorException) t;
MessageHelper.rejected(delivery, cause.asErrorCondition());
} else {
logger.debug("error processing request [resource: {}, op: {}]: {}", targetAddress, message.getSubject(), t.getMessage());
MessageHelper.rejected(delivery, ProtonHelper.condition(AmqpError.INTERNAL_ERROR, "internal error"));
}
return null;
});
}
use of org.eclipse.hono.auth.HonoUser in project hono by eclipse.
the class HonoSaslAuthenticator method process.
@Override
public void process(final Handler<Boolean> completionHandler) {
String[] remoteMechanisms = sasl.getRemoteMechanisms();
if (remoteMechanisms.length == 0) {
LOG.debug("client provided an empty list of SASL mechanisms [hostname: {}, state: {}]", sasl.getHostname(), sasl.getState().name());
completionHandler.handle(false);
} else {
String chosenMechanism = remoteMechanisms[0];
LOG.debug("client wants to authenticate using SASL [mechanism: {}, host: {}, state: {}]", chosenMechanism, sasl.getHostname(), sasl.getState().name());
Future<HonoUser> authTracker = Future.future();
authTracker.setHandler(s -> {
if (s.succeeded()) {
HonoUser user = s.result();
LOG.debug("authentication of client [authorization ID: {}] succeeded", user.getName());
Constants.setClientPrincipal(protonConnection, user);
succeeded = true;
sasl.done(SaslOutcome.PN_SASL_OK);
} else {
LOG.debug("authentication failed: " + s.cause().getMessage());
sasl.done(SaslOutcome.PN_SASL_AUTH);
}
completionHandler.handle(Boolean.TRUE);
});
byte[] saslResponse = new byte[sasl.pending()];
sasl.recv(saslResponse, 0, saslResponse.length);
verify(chosenMechanism, saslResponse, authTracker.completer());
}
}
use of org.eclipse.hono.auth.HonoUser in project hono by eclipse.
the class AuthenticationServerClient method getToken.
private void getToken(final ProtonConnection openCon, final Future<HonoUser> authResult) {
final ProtonMessageHandler messageHandler = (delivery, message) -> {
String type = MessageHelper.getApplicationProperty(message.getApplicationProperties(), AuthenticationConstants.APPLICATION_PROPERTY_TYPE, String.class);
if (AuthenticationConstants.TYPE_AMQP_JWT.equals(type)) {
Section body = message.getBody();
if (body instanceof AmqpValue) {
final String token = ((AmqpValue) body).getValue().toString();
HonoUser user = new HonoUserAdapter() {
@Override
public String getToken() {
return token;
}
};
LOG.debug("successfully retrieved token from Authentication service");
authResult.complete(user);
} else {
authResult.fail("message from Authentication service contains no body");
}
} else {
authResult.fail("Authentication service issued unsupported token [type: " + type + "]");
}
};
openReceiver(openCon, messageHandler).compose(openReceiver -> {
LOG.debug("opened receiver link to Authentication service, waiting for token ...");
}, authResult);
}
Aggregations