4 releases (2 breaking)
0.3.2 | Jul 31, 2022 |
---|---|
0.3.1 |
|
0.3.0 | Dec 22, 2019 |
0.2.0 | Dec 25, 2018 |
0.1.0 | Nov 27, 2018 |
#12 in #compliance
34KB
785 lines
miss-demeanor
An webhook-driven executor with a plugin interface designed for audit compliance
Why miss-demeanor?
- The name is clever and Missy Elliott is great.
- miss-demeanor is heavily parallelized and as it is written in Rust, the type system handles checking a lot of those multithreading concerns for you. It handles requests quickly, statelessly, and is specifically designed to avoid deadlocks.
- miss-demeanor is pluggable so you are the maker of your own workflow here.
- The plugin interface is flexible and dead simple.
- See 1. It is still the most compelling reason.
Building miss-demeanor
Install the Rust toolchain. Instructions can be found here.
Navigate to miss-demeanor/
and run cargo build --release
.
Your executable will be located at ./target/release/miss-demeanor
.
Using TLS with miss-demeanor
Currently the TLS library that miss-demeanor uses only supports a PCKS12/DER identity format. This is not my choice and I hope to eventually be able to support PEM identites for the server.
To easily generate a self-signed certificate for testing, run:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365
openssl pkcs12 -export -out identity.pfx -inkey key.pem -in cert.pem
The invocation is pretty simple: provide the path to -f
for your PKCS12 identity file and use
the environment variable PKCS12_PASSWORD
to supply the password.
Config format
The config file is written in TOML.
Here is a sample config file with some comment explanations:
trigger_type = "c_abi" # Can also be "interpreted"
[server]
server_type = "webhook" # Can also be "unix_socket"
listen_addr = "127.0.0.1:8080" # Must be in the format IP:PORT
use_tls = false # You probably want this on unless you are running it over localhost - must pass -f on CLI when this is enabled
# One server endpoint
[[server.endpoints]]
path = "/pr" # URL path
trigger_name = "github-pr" # Unique name
# Another server endpoint
[[server.endpoints]]
path = "/merged"
trigger_name = "github-merged"
# Plugins
[[triggers]]
name = "github-merged" # Unique name
plugin_path = "./example-plugins/golang/github-merged.so" # Path to C ABI compatible shared object (.so)
The idea is to expose the server configuration declaratively. The config file controls everything about the server - endpoints, listen address, transport layer, plugins associated with each endpoint, etc.
Writing plugins
How do you actually write a plugin for miss-demeanor though?
First check out miss-demeanor/example-plugins/
for code
examples.
The longer answer is this: a plugin can be one of two formats.
- It can be defined as any dynamic library (.so file on Linux for example)
that exports a C ABI compatible function symbol
(C ABI compatible simply means that it follows C calling
convention, etc. - that at a binary level it is
indistinguishable from C binaries) named
trigger
. To use this feature, set trigger type toc_abi
.
C function signature:
int trigger(void *http_request);
Rust function signature:
fn trigger(http_request: *const libc::c_void) -> libc::c_int;
C example:
#include "trigger.h"
#include <stdio.h>
int trigger(void *http_request) {
printf("%s\n", request_get_method(http_request));
return 0;
}
Golang example:
// #include "trigger.h"
// #cgo LDFLAGS: -lmissdemeanor -ldl
import "C"
import "unsafe"
import "fmt"
//export trigger
func trigger(http_request unsafe.Pointer) C.int {
fmt.Println(C.GoString(C.request_get_method(http_request)))
}
func main {}
Rust example:
use missdemeanor::CRequest;
#[no_mangle]
pub fn trigger(http_request: *const CRequest) -> libc::c_int {
let method = match unsafe { request.as_ref() }.get_method() {
Ok(b) => b,
Err(e) => {
println!("{}", e);
return 1;
},
};
println!("{}", method);
}
- It can be defined as an interpreted script with a shebang at the beginning. To use this feature,
set trigger type to
interpreted
.
Python example:
#!/usr/bin/python
import sys
method = sys.argv[1]
print(method)
Dependencies
~10–23MB
~333K SLoC