wiki:KrakenRpc

Kraken RPC

In closed/secured network environment, or NAT'ed network, you generally cannot connect to client. Kraken RPC enables bi-direction RPC invocation in these environments. Since RPC connection works just as a transport, you can create RPC session to either direction (client to server, or server to client) as long as RPC service is bound to that connection.

For example, Let's imagine that Kraken Sentry connects to Kraken Base over the public internet. Kraken Sentry is installed in the NAT'ed network. Even in this network configuration, Kraken Base can connect RPC session to RPC services which provided by Kraken Sentry.

Moreover, Kraken RPC provides declarative service programming. See calculator service and client example.

Author

Commands

Access Control

rpc.guid

Print GUID of local RPC agent:

kraken@Future bin> rpc.guid
ae6d2925-24de-400b-8f04-9bfa31f8876f

You can grant access privilege to other RPC clients based on GUID.

rpc.registerPeer

Register new peer RPC agent:

kraken@Future bin> rpc.registerPeer
Description

        register rpc peer

Arguments

        1. guid: the guid of peer (required)
        2. password: the password of peer (required)
        3. trust level: 1(untrust), 2(low), 3(medium), 4(high) (required)

kraken@Future bin> rpc.registerPeer test-guid PASSWORD 4
test-guid registered

You should set password for non-SSL channel. For now, SSL channel do not use password for peering.

rpc.unregisterPeer

kraken@Future bin> rpc.unregisterPeer
Description

        unregister rpc peer

Arguments

        1. guid: peer's guid (required)

kraken@Future bin> rpc.unregisterPeer test-guid
test-guid unregistered

rpc.peers

Print all registered RPC peers:

kraken@Future bin> rpc.peers
RPC Peers
--------------
test-guid

Connection & Session

Manage RPC port binding, connections, and sessions.

rpc.connections

Print all current RPC connections (inbound and outbound):

kraken@Future bin> rpc.connections
RPC Connections
----------------
id=4084687, peer=(b6b648b7-4605-4b20-be40-3d4778a58fdb, /127.0.0.1:54291), trusted level=High, ssl=true

In this example, "b6b648b7-4605-4b20-be40-3d4778a58fdb" is a peer GUID. /127.0.0.1:54291 is a remote address. "ssl=true" means SSL connection.

rpc.setprop

rpc.sessions

Print all RPC sessions over the RPC connection:

kraken@Future bin> rpc.sessions
Description

        list all sessions of the connection

Arguments

        1. cid: connection id (required)

kraken@Future bin> rpc.sessions 4084687
RPC Sessions
---------------
id=0, service=rpc-control, peer=/127.0.0.1:54291

All connections have rpc-control session by default.

rpc.services

Print all bound RPC service on the connection:

kraken@Future bin> rpc.services
Description

        list all bound services

Arguments

        1. cid: connection id (required)

kraken@Future bin> rpc.services 4084687
Service Bindings
-------------------
name=logdb, class=org.krakenapps.logdb.impl.LogRpcService
name=rpc-control, class=org.krakenapps.rpc.impl.RpcControlService
name=logdb-mapreduce, class=org.krakenapps.logdb.impl.MapReduceRpcService

RPC client can create new RPC session for RPC service.

rpc.bindings

Print all listen port bindings:

kraken@Future bin> rpc.bindings
Port Bindings
---------------
addr=0.0.0.0, port=7140, key=rpc-agent, trust=rpc-ca]

No RPC port will be opened by default. You should open new RPC port yourself. Use rpc.open or rpc.openSsl command to open new listening port.

rpc.open

kraken@Future bin> rpc.open
Description

        open rpc port

Arguments

        1. port: rpc port (required)
        2. ip: bind address. '0.0.0.0' by default (optional)

Open cleartext RPC port. default bind address is '0.0.0.0'.

rpc.openSsl

kraken@Future bin> rpc.openSsl
Description

        open rpc ssl port

Arguments

        1. port: rpc listening port for ssl (required)
        2. key alias: key alias. use 'keystore.list' command to list all registered key aliases. Keystore should contain public and private key pair. e.g. PKCS12 keystore (required)
        3. trust alias: trust alias. use 'keystore.list' command to list all registered key aliases. Trusted keystore should contain public key of certificate authority (required)
        4. ip: bind address. '0.0.0.0' by default (optional)

Use registered keystore aliases for SSL port bindings.

rpc.close

kraken@Future bin> rpc.close
Description

        close rpc port or rpc ssl port

Arguments

        1. port: rpc port or rpc ssl port (required)
        2. ip: bind address. '0.0.0.0' by default (optional)

rpc.connect

rpc.connectSsl

rpc.disconnect

rpc.disconnectAll

rpc.requestPeering

Blocking Call

rpc.waitings

kraken@Future bin> rpc.waitings
Description

        list all waiting calls of the connection

Arguments

        1. cid: connection id (required)

You can figure out current blocking RPC calls. Use 'rpc.cancel' command to cancel blocking RPC call.

rpc.cancel

kraken@Future bin> rpc.cancel
Description

        cancel rpc calls of the connection

Arguments

        1. cid: connection id (required)
        2. call id: call id (required)

rpc.props

Tutorial

Calculator Service

CalculatorService.java

package org.krakenapps.examples.rpc.calc;

import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Provides;
import org.apache.felix.ipojo.annotations.ServiceProperty;
import org.krakenapps.rpc.RpcMethod;
import org.krakenapps.rpc.SimpleRpcService;

@Component(name = "calc-service")
@Provides
public class CalculatorService extends SimpleRpcService {

	@SuppressWarnings("unused")
	@ServiceProperty(name = "rpc.name", value = "calc")
	private String name;

	@RpcMethod(name = "add")
	public int add(int a, int b) {
		return a + b;
	}
}

metadata.xml

<ipojo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="org.apache.felix.ipojo http://felix.apache.org/ipojo/schemas/CURRENT/core.xsd"
	xmlns="org.apache.felix.ipojo">
	<instance component="calc-service" />
</ipojo>

Calculator Client

RpcConnectionProperties props = new RpcConnectionProperties(remote);
props.setPassword(password);

RpcClient client = new RpcClient(guid);
RpcConnection conn = client.connect(props);
RpcSession session = conn.createSession("calc");
Object value = session.call("add", new Object[] { 100, 200 });

System.out.println(value);
client.close();

Messaging Patterns

You can pass only java primitive types (null, Boolean, Short, Integer, Long, String, Date, InetAddress, Float, Double, byte[]) and collection types (Map<String, Object> or Collection) for arguments. If you want to send user-defined compound types, use  PrimitiveConverter to serialize arbitrary user-defined class instance to primitive mixture, or parse primitive mixtures to user-defined class instance. See  PrimitiveConverterTest unit test for usage example. However, I DO NOT recommend PrimitiveConverter for high performance scenario. It is somewhat slow because it uses java reflection.

Synchronous (aka blocking) Call

If you want blocking call, use:

Object call(String method, Object... params) throws RpcException, InterruptedException;

Object call(String method, Object[] params, long timeout) throws RpcException, InterruptedException;

Asynchronous Call

If you want non-blocking and return value, use:

RpcAsyncResult call(String method, Object[] params, RpcAsyncCallback callback); 

Post (aka fire-and-forget)

When you do not require return value, or want just notification, use:

void post(String method, Object... params); 

Protocol

Peering

For privileged RPC invocation, each node should be authenticated by the other. To create any RPC session (call session-request of rpc-control session), you should peering first.

Steps

  1. Each peer set rpc-control for session 0.
  2. Each peer send peering-request RPC call with guid string argument.
    •  RpcControlService.handlePeeringRequest will handle peering-request method call.
    • If channel uses non-SSL protocol, send reject response with [ "challenge", guid, nonce ]. Nonce is used for password hashing.
    • If channel uses SSL protocol, RPC control service try to find peer in peer registry. Registered peer will be granted specified trust level. Non-registered peer will have Low-trust. Then RPC control service send success response with [ "success", guid, trust level ]. (Untrusted 1, Low 2, Medium 3, High 4)
  3. Each peer handles "success" or "challenge" response:
    • For "success" response, peer set trusted level (trusted level by the other) and finishes peering process.
    • For "challenge" response, peer call "authenticate" method with [ guid, hash ]. hash is SHA1(password + nonce).
  4.  RpcControlService.handleAuthenticate will handle authenticate method call.
    • Calculates hash using nonce and saved password, then matches hash value.
    • Sets trust level, and sends challenge result with [ result, trust level ]. result is boolean (true if success), and trust level is between 1-4. (Untrusted 1, Low 2, Medium 3, High 4)

See Also

  • Kraken CA - Create X.509 and PKCS12 certificate for SSL RPC channel.
  • Kraken Codec - Kraken RPC protocol encodes and decodes payload using Kraken Codec.
  • Kraken Sentry and Kraken Base - Kraken RPC is initially designed for bi-direction RPC between agent and SIEM server.

Release History

  • 1.5.1