rupicola

package module
v0.0.0-...-5d19dc8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 20, 2022 License: GPL-3.0 Imports: 27 Imported by: 0

README

Rupicola

Rust Remote Procedure Caller Application

Rupicola is a program that allows calling procedures on remote machines. Procedures to be called are part of application configuration.

How to call anything?

This section briefly describe how to use server from client perspective.

Server support HTTP/1.1 and require valid HTTP POST request. If permission checking is enabled then request should contains basic auth with login and password. Only exception from this is made when method and bind point is explicit marked as allowing unchecked requests from loopback.

Body of request contains valid JSON RPC 2.0. For details see http://www.jsonrpc.org/specification.

Note that all methods using arguments require passing arguments in request by-name, and positional parameters are not supported yet.

Streaming

Streaming version use HTTP Chunked response, and thus require HTTP/1.1 compatible client. Current implementation stream stdout from called executable "as is".

Configuration

This section provides detailed information about configuration files. Configuration file use YAML format. Below is detailed rundown of all configuration sections.

Configuration contains following sections:

  • include
  • protocol
  • limits
  • log
  • methods
include

To include other configuration files use

include:
  - file 1
  - file 2: flag

First ever appearance of method or any other definition is used and it redefinition is ignored. Default action for missing included file is warning (non fatal). For now maximum depth is hardcoded to 10. Each file path can be marked with boolean flag. If flag is true then config file is required, and rupicola, will exit with error code. Default value for flag is false.

protocol

Section used to configure bind points, auth mode and change default path to streaming and RPC subsystems.

bind

Define listening bindpoint. This object have following fields: type, address, port, allow_private

allow_private is special flag which indicate if request from loopback is handled without checking credentials. This flag can be used on any bind point type. Default value is false.

Note that any field that is not highlighted is ignored during parsing configuration. For defining http listening endpoint use:

type: http
address: any.ipv4.address
port: int

To use https:

type: https
address: any.ipv4.address
key: path/to/key
cert: path/to/cert
port: int

To use unix socket

type: unix
address: /path/to/socket
mode: int
gid: int
uid: int

Default values for mode is 666, gid - inherited from running process, uid - inherited from running process.

auth-basic

To enforce checking auth you can specify login and password. Server use simple http basic auth. Please note that this method is safe when used with https or unix bind point type.

login: any-string

Password field is string

Hashed version of password use following modes:

  • Standard BSD hash
  • Enhanced DES-based hash
  • MD5 crypt
  • HMAC-SHA1 hash
  • SHA-256 based
  • SHA-512 based
  • standard unix crypt

To generate MD5 based hash or standard unix use for example openssl passwd.

passowrd: $1$sRN7MKRJ$XfbAXBpoOphTIhBRZuPAl.
password: ktsudxoI79bPk

This is recommended method of storing password.

To disable crypt and force plaintext password check set field is_plaintext to true

is_plaintext: true
uri

To change default uri path for streamed and RPC define

uri:
    streamed: /path
    rpc: /path

Both fields are optional and require string field type. Note that path must be prefixed with trailing '/'.

Parameter Default
streamed /streamed
rpc /jsonrpc
limits

This field allow to set default limits for methods. All fields are optional Currently supported fields:

Name Default Unit Description
read-timeout 20000 ms Maximum time spend for next portion of data from external source. Setting it to 0 disables timeout
exec-timeout 0 ms Maximum time spend while processing request. Setting it to 0 disables timeout (which is default). NOTE: Currently this is not working at all
payload-size 5242880 byte Maximum size for request (RPC and stream). THIS IS GLOBAL MAXIMUM (methods cannot change it)
max-response 5242880 byte Maximum response for RPC. Could be changed on per-method level
request-wait 30000 ms Maximum timeout used when waiting for client request. THIS IS GLOBAL MAXIMUM (methods cannot change it). Setting it to 0 disables timeout
log

Configure how handle output from logs. Possible output sink is syslog or stdout. You can change log level with level: string-level value.

Possible levels are: off, trace, debug, info, warn, error If backend is not specified then stdout is used by default. backend: stdout | syslog to change path used by syslog use path: /path/to/socket

methods

This is place where you specify how handle processing request. Construction for method definition is as follow:

method-name:
    private: boolean (default: false)
    include_stderr: boolean (default: false)
    streamed: boolean
    encoding: utf-8 | base64 (default: utf-8)
    params: (default: nil)
        parameter_name:
            type: string | number | bool
            optional: boolean (default: false)
    invoke:
        exec: string
        args: (default: nil)
            - arg0
            - {param: string}
            - [arg1, {param: string}]
            - ["arg 2", {param: string, skip: boolean}]
    	run-as: (default: nil)
        	gid: int
        	uid: int
    output: (default: nil)
        format: json
    limits: (default: nil)
        - fields from limits (same as global level, default: from global)

All methods are defined as object with keys that reflect names. All names should be string value. All methods by default are public which means they are accessible from loopback and external addresses. To force only local access specify flag 'private' to true. Method can work only as streamed or RPC. This aspect is controlled by settings field 'streamed' to either true or false.

For special function it's also possible to encode raw byte output from invoked application as Base64. This is controlled by field 'encoding'. Default all stdout is converted to UTF-8.

All methods can require parameters. Only supported method of providing them is by-name. All parameters should have valid string name and specified type. If parameter is flagged as optional (optional: true) then all arguments using this parameters are ignored in invocation.

To specify application to run it's required to set exec field to correct path.

All arguments in args list are passed to executable unless:

  • argument use optional field, and this field is missing in request,
  • argument use optional phantom field, and this field is missing in request.

Phantom field is used to bind presence of given argument to presence of parameter - without using argument value.

Values can be nested using lists, but going too deep is not recommended. For example this is perfectly valid argument definition [[[[[[a],[b]],[[c]]],[" "]], [{param: uri}]], [" cba"]] and it could be simplified to ["abc ", {param: uri}, " cba"]

To use parameter in normal mode use {param: name}. Phantom mode use field skip with value true: {param: name, skip:true}.

Special parameter value is 'self'. This get request in JSON format and pass as single argument to executable.

Default all methods are executed with privilages of user running main process. To change user running procedure define field 'run-as' with 'gid' and 'uid' specified as required. Both fields are required.

As default output from executable is treated as series of bytes, but this can be changed to JSON. In this mode expected output from executable is valid JSON document. To change mode use

output:
    format: json
Example

For example configuration see examples/sample.conf

Contact and License

Rupicola is written by Marcin Kocot for Korbank S.A.. The primary distribution point is https://github.com/korbank/rupicola-go.

Rupicola is distributed under GNU GPL v3 license. See LICENSE file for details.

GPL terms do not apply to the invoked procedures provided by configuration file.

Documentation

Index

Constants

View Source
const (
	// HTTP - HTTP transport over TCP
	HTTP BindType = 0
	// HTTPS - HTTPS transport over TCP
	HTTPS = 1
	// Unix - HTTP transport over unix socket
	Unix = 2
)

Variables

View Source
var Logger = log.Nop()

Functions

func ListenAndServe

func ListenAndServe(configuration *Config) error

func ListenKeepAlive

func ListenKeepAlive(network, address string) (ln net.Listener, err error)

ListenKeepAlive start listening with KeepAlive active

func ListenUnixLock

func ListenUnixLock(addr string) (net.Listener, error)

ListenUnixLock is like net.ListenUnix but with lock

func SetUserGroup

func SetUserGroup(process *exec.Cmd, m *MethodDef)

SetUserGroup assign UID and GID to process

Types

type Backend

type Backend int8

Backend define log backend

const (
	// BackendStdout write to stdout
	BackendStdout Backend = 1 << iota
	// BackendSyslog write to syslog
	BackendSyslog Backend = 1 << iota
	// BackendStderr write to stderr (default)
	BackendStderr Backend = 1 << iota
	// BackendKeep keep current output
	BackendKeep Backend = 1 << iota
)

type Bind

type Bind struct {
	Type         BindType
	Address      string
	Port         uint16
	AllowPrivate bool
	// Only for HTTPS
	Cert string
	// Only for HTTPS
	Key string
	// Only for Unix [default=660]
	Mode os.FileMode
	UID  int
	GID  int
}

Bind - describe listening address binding

func (*Bind) Bind

func (bind *Bind) Bind(mux *http.ServeMux, limits Limits) error

Bind to interface and Start listening using provided mux and limits

type BindType

type BindType int

BindType ...

type Config

type Config struct {
	Protocol Protocol
	Limits   Limits
	Log      LogDef
	Methods  map[string]*MethodDef
}

Config ...

func NewConfig

func NewConfig() *Config

NewConfig - create configuration with default values

func ReadConfig

func ReadConfig(configFilePath string) (*Config, error)

ReadConfig from file

func (*Config) SetLogging

func (conf *Config) SetLogging()

SetLogging to expected values THIS IS NOT THREAD SAFE

type Limits

type Limits struct {
	ReadTimeout time.Duration
	ExecTimeout time.Duration
	PayloadSize uint32
	MaxResponse uint32
}

Limits ...

type LogDef

type LogDef struct {
	Backend
	LogLevel
	Path string
}

LogDef holds logging definitions

type LogLevel

type LogLevel int8

LogLevel describe logging level

const (
	// LLOff Disable log
	LLOff LogLevel = iota
	// LLDebug most detailed log level (same as Trace)
	LLDebug
	// LLInfo only info and above
	LLInfo
	// LLWarn only warning or errors
	LLWarn
	// LLError only errors
	LLError
)

type MethodDef

type MethodDef struct {
	Streamed   bool
	Private    bool
	Encoding   MethodEncoding
	Params     map[string]MethodParam
	InvokeInfo struct {
		Exec  string
		Delay time.Duration
		Args  []methodArgs
		RunAs RunAs
	}
	// Pointer because we need to know when its unsed
	Limits *MethodLimits

	// unused parameter
	Output interface{}
	// contains filtered or unexported fields
}

MethodDef ...

func (*MethodDef) CheckParams

func (m *MethodDef) CheckParams(params map[string]interface{}) error

CheckParams ensures that all required paramters are present and have valid type

func (*MethodDef) Invoke

func (m *MethodDef) Invoke(ctx context.Context, req rupicolarpc.JsonRpcRequest) (interface{}, error)

Invoke is implementation of jsonrpc.Invoker

func (*MethodDef) Validate

func (m *MethodDef) Validate() error

Validate ensure correct method definition

type MethodEncoding

type MethodEncoding int

MethodEncoding ...

const (
	// Utf8 - Default message encoding
	Utf8 MethodEncoding = iota
	// Base64 - Encode message as base64
	Base64
	// Base85 - Encode message as base85
	Base85
)

type MethodLimits

type MethodLimits methodLimits

MethodLimits define execution limits for method

type MethodParam

type MethodParam struct {
	Type     MethodParamType
	Optional bool
	// contains filtered or unexported fields
}

MethodParam ...

type MethodParamType

type MethodParamType int

MethodParamType ...

const (
	// String - Method parameter should be string
	String MethodParamType = iota
	// Int - Method parameter should be int (not float)
	Int
	// Bool - Method parameter should be bool
	Bool
	//Number - Any number (for now this is alias)
	Number
)

func (MethodParamType) String

func (mpt MethodParamType) String() string

type Protocol

type Protocol struct {
	Bind []*Bind

	AuthBasic struct {
		Login    string
		Password string
	}

	URI struct {
		Streamed string
		RPC      string
	}
}

Protocol - define bind points, auth and URI paths

type RunAs

type RunAs struct {
	UID uint32
	GID uint32
}

RunAs ...

type UnixListenerWithLock

type UnixListenerWithLock struct {
	net.Listener
	// contains filtered or unexported fields
}

FileLock guard

func (*UnixListenerWithLock) Close

func (f *UnixListenerWithLock) Close() error

Close listener and remove lock

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL