Search in sources :

Example 6 with HonoUser

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();
    }
}
Also used : ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) HonoUser(org.eclipse.hono.auth.HonoUser) Source(org.apache.qpid.proton.amqp.transport.Source)

Example 7 with HonoUser

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();
        }
    }
}
Also used : ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) HonoUser(org.eclipse.hono.auth.HonoUser)

Example 8 with HonoUser

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;
    });
}
Also used : HttpURLConnection(java.net.HttpURLConnection) ProtonConnection(io.vertx.proton.ProtonConnection) ProtonReceiver(io.vertx.proton.ProtonReceiver) AmqpErrorException(org.eclipse.hono.util.AmqpErrorException) ProtonDelivery(io.vertx.proton.ProtonDelivery) DecodeException(io.vertx.core.json.DecodeException) Autowired(org.springframework.beans.factory.annotation.Autowired) EventBusMessage(org.eclipse.hono.util.EventBusMessage) HonoUser(org.eclipse.hono.auth.HonoUser) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) ServiceConfigProperties(org.eclipse.hono.config.ServiceConfigProperties) Constants(org.eclipse.hono.util.Constants) Message(org.apache.qpid.proton.message.Message) ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) JsonObject(io.vertx.core.json.JsonObject) AmqpError(org.apache.qpid.proton.amqp.transport.AmqpError) Vertx(io.vertx.core.Vertx) ProtonHelper(io.vertx.proton.ProtonHelper) ProtonQoS(io.vertx.proton.ProtonQoS) MessageHelper(org.eclipse.hono.util.MessageHelper) Future(io.vertx.core.Future) Objects(java.util.Objects) Optional(java.util.Optional) ProtonSender(io.vertx.proton.ProtonSender) ClaimsBasedAuthorizationService(org.eclipse.hono.service.auth.ClaimsBasedAuthorizationService) MessageConsumer(io.vertx.core.eventbus.MessageConsumer) AuthorizationService(org.eclipse.hono.service.auth.AuthorizationService) HonoUser(org.eclipse.hono.auth.HonoUser) AmqpErrorException(org.eclipse.hono.util.AmqpErrorException) DecodeException(io.vertx.core.json.DecodeException)

Example 9 with HonoUser

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());
    }
}
Also used : HonoUser(org.eclipse.hono.auth.HonoUser)

Example 10 with HonoUser

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);
}
Also used : ProtonConnection(io.vertx.proton.ProtonConnection) ProtonReceiver(io.vertx.proton.ProtonReceiver) HonoUserAdapter(org.eclipse.hono.auth.HonoUserAdapter) Logger(org.slf4j.Logger) LoggerFactory(org.slf4j.LoggerFactory) Vertx(io.vertx.core.Vertx) Autowired(org.springframework.beans.factory.annotation.Autowired) HonoUser(org.eclipse.hono.auth.HonoUser) MessageHelper(org.eclipse.hono.util.MessageHelper) Future(io.vertx.core.Future) AuthenticationConstants(org.eclipse.hono.service.auth.AuthenticationConstants) Objects(java.util.Objects) ConnectionFactory(org.eclipse.hono.connection.ConnectionFactory) Section(org.apache.qpid.proton.amqp.messaging.Section) ProtonClientOptions(io.vertx.proton.ProtonClientOptions) AmqpValue(org.apache.qpid.proton.amqp.messaging.AmqpValue) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) Qualifier(org.springframework.beans.factory.annotation.Qualifier) AsyncResult(io.vertx.core.AsyncResult) Handler(io.vertx.core.Handler) HonoUser(org.eclipse.hono.auth.HonoUser) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) HonoUserAdapter(org.eclipse.hono.auth.HonoUserAdapter) Section(org.apache.qpid.proton.amqp.messaging.Section) AmqpValue(org.apache.qpid.proton.amqp.messaging.AmqpValue)

Aggregations

HonoUser (org.eclipse.hono.auth.HonoUser)11 ProtonConnection (io.vertx.proton.ProtonConnection)4 ResourceIdentifier (org.eclipse.hono.util.ResourceIdentifier)4 Future (io.vertx.core.Future)2 Vertx (io.vertx.core.Vertx)2 JsonObject (io.vertx.core.json.JsonObject)2 ProtonClientOptions (io.vertx.proton.ProtonClientOptions)2 ProtonReceiver (io.vertx.proton.ProtonReceiver)2 Objects (java.util.Objects)2 Source (org.apache.qpid.proton.amqp.transport.Source)2 Message (org.apache.qpid.proton.message.Message)2 MessageHelper (org.eclipse.hono.util.MessageHelper)2 Autowired (org.springframework.beans.factory.annotation.Autowired)2 AsyncResult (io.vertx.core.AsyncResult)1 Handler (io.vertx.core.Handler)1 MessageConsumer (io.vertx.core.eventbus.MessageConsumer)1 DecodeException (io.vertx.core.json.DecodeException)1 ProtonDelivery (io.vertx.proton.ProtonDelivery)1 ProtonHelper (io.vertx.proton.ProtonHelper)1 ProtonMessageHandler (io.vertx.proton.ProtonMessageHandler)1