Request Rewrite Plugins¶
Mayhem has support for request rewriting via plugins, which are standalone programs that implement a protobuf interface and expose it via gRPC.
The interface details are below. But first...
Do I Need This?¶
We've tried to make Mayhem work out of the box for as many use-cases as we can, and we'll keep adding more. The request rewrite plugin is intended as a kind of escape-hatch for situations where an API has requirements that we can't currently meet out of the box.
Here are the cases we had in mind when building the feature:
Just In Time Authentication¶
In any situation where the authentication needs to change during a testing job, we don't currently have a solution directly in Mayhem for API.
A request rewrite plugin can inject the appropriate credentials at whatever cadence your API requires.
Request Digesting/Signing¶
If your API uses any kind of digesting or signing as authentication measures, Mayhem will be unable to generate valid requests.
A request rewrite plugin can compute and inject these per-request checksums or signatures.
Something else?¶
The request plugin interface is extremely open-ended, and can rewrite just about any part of any request.
If you're thinking about using a rewrite plugin for any reason, please get in touch. This is a very young, very raw feature, and we'd like to know how people are using it, and how we can make it better!
Interface¶
Invocation¶
To add a request rewrite plugin to an API testing run, use the
--rewrite-plugin <path-to-plugin-executable>
argument to mapi
run
.
Executable gRPC Server¶
mapi will run the executable with no command-line arguments, and expects it to be a long-lived process that: * listens for gRPC traffic on a localhost port * prints the port number, followed by a newline, to stdout as the first line
Beyond that, it can do whatever it wants. Additional stdout/stderr output from the plugin are forwarded to the mapi debug logs.
At the end of the testing run, mapi will attempt to kill the plugin process.
Protobuf¶
Request rewrite plugins implement the following protobuf interface:
syntax = "proto3";
package mapi.rewrite;
service RewritePlugin {
rpc Rewrite(Request) returns (Request);
}
message Request {
message Header {
bytes name = 1;
bytes value = 2;
}
string url = 1;
repeated Header headers = 2;
bytes body = 3;
string http_method = 4;
}
Example¶
Here's an example request rewrite plugin, which does... absolutely nothing, just returning the original request unchanged!
First, generate all of the gRPC and protobuf boilerplate from the .proto above:
$ pip install grpcio-tools
$ python -m grpc_tools.protoc --python_out=. --grpc_python_out=. -I. request-rewrite-plugin.proto
Then create a python program which implements the RewritePluginServicer
, stands
up a gRPC server, and lets mapi know what port it's listening on:
#!/usr/bin/env python
import sys
from concurrent import futures
import grpc
import request_rewrite_plugin_pb2
import request_rewrite_plugin_pb2_grpc
## implement the RewritePlugin interface
class RewritePluginServicer(request_rewrite_plugin_pb2_grpc.RewritePluginServicer):
def Rewrite(self, request, context):
## well, this isn't very interesting :)
return request
if __name__ == '__main__':
## boot up the gRPC server
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
request_rewrite_plugin_pb2_grpc.add_RewritePluginServicer_to_server(
RewritePluginServicer(), server)
server.add_insecure_port('127.0.0.1:50051')
server.start()
## inform mapi of the port we're listening on
print("50051")
sys.stdout.flush()
server.wait_for_termination()
Make sure your .py file is executable, then pass it to mapi via
--rewrite-plugin
. That's it!
More Examples¶
Please visit our GitHub Repository for more examples that you can try yourself!
Caveats and Cautions¶
bytes, Not string!¶
Mayhem API testing requests are not always representable as strings. Be careful!
Subject to Change¶
All of this is volatile and subject to change. If you're using this feature, please get in touch, so that we can keep you in the loop as we consider refinements and changes.
Injected Header Secrets¶
If a rewrite plugin adds a sensitive header into the request, option --redact-header
may be used to suppress the
value of the added header in the reports. See
Suppressing Header Secrets
for more details.