You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
xmppipe/README.md

369 lines
7.8 KiB
Markdown

8 years ago
xmppipe: stdio over XMPP
========================
8 years ago
xmppipe redirects stdin/stdout in a shell pipeline to an XMPP MUC
(XEP-0045). xmppipe supports flow control using stream management
8 years ago
(XEP-0198) and can optionally deal with overload by acting as a circuit
8 years ago
breaker or by discarding messages.
8 years ago
xmppipe works with line oriented tools like grep, sed and
awk by outputting each message as a newline terminated,
[percent-encoded](https://en.wikipedia.org/wiki/Percent-encoding) string.
8 years ago
xmppipe can be used in shell scripts to quickly write interactive bots
for monitoring systems or for sending alerts.
8 years ago
Usage
-----
xmppipe [*options*]
XMPPIPE_USERNAME=me@example.com
XMPPIPE_PASSWORD="password"
xmppipe -o muc
8 years ago
Requirements
------------
* [libstrophe](https://github.com/strophe/libstrophe)
libstrophe 0.9.2 or later is required for [TLS certificate
verification](https://github.com/strophe/libstrophe/issues/100).
8 years ago
Build
-----
$ make
Tests
-----
# Install bats:
# apt-get install bats
# git clone https://github.com/sstephenson/bats.git # or from git
make test
Sandboxing
----------
xmppipe uses a sandbox to try to restrict itself to whatever operations
are necessary for interacting with stdio.
There are 2 sandboxes:
* a permissive "init" sandbox allowing network connections to the
XMPP server
* after the connection is established, a stricter "stdio" sandbox
restricting the process to stdio operations
The effectiveness of the sandbox depends on which mechanism is used. By
default:
* Linux:
* init: seccomp(2)
* stdio: seccomp(2)
* OpenBSD:
* init: pledge(2)
* stdio: pledge(2)
* FreeBSD:
* init: setrlimit(2)
* stdio: setrlimit(2)/capsicum(4)
* other: setrlimit(2)
* init: setrlimit(2)
* stdio: setrlimit(2)
Selecting the sandbox can be done at compile time. For example, to use
the "rlimit" sandbox:
XMPPIPE_SANDBOX=rlimit make
If a sandbox is interfering with normal operation, please open an issue.
To disable the sandbox, compile using the "null" sandbox:
XMPPIPE_SANDBOX=null make
8 years ago
Options
-------
-u, --username *JID*
8 years ago
: XMPP username: takes precedence over environment variable
-p, --password *password*
8 years ago
: XMPP password: takes precedence over environment variable
-r, --resource *resource*
8 years ago
: XMPP resource, used as the nickname in the MUC
-o, --output *output*
8 years ago
: XMPP MUC name
Default: stdout-*hostname*-*uid*
8 years ago
-S, --subject *subject*
8 years ago
: XMPP MUC subject
-a, --address *address:port*
8 years ago
: Specify the IP address and port of the XMPP server
-d, --discard
8 years ago
: Discard stdin when MUC is empty
-D, --discard-to-stdout
8 years ago
: Discard stdin and print to local stdout
-e, --ignore-eof
8 years ago
: Ignore stdin EOF
-s, --exit-when-empty
8 years ago
: Exit when MUC is empty
-x, --base64
8 years ago
: Base64 encode/decode data
-b, --buffer-size *size*
8 years ago
: Size of read buffer
-I, --interval *interval*
8 years ago
: Request stream management status every interval messages
8 years ago
-k, --keepalives *seconds*
8 years ago
: Periodically send a keepalive
-K, --keepalive-failures *count*
8 years ago
: Number of keepalive failures before exiting
-P, --poll-delay *ms*
8 years ago
: Poll delay
-v, --verbose
8 years ago
: Increase verbosity
--no-tls-verify
: Disable TLS certificate verification
Decoding Percent-Encoded Strings
8 years ago
--------------------------------
8 years ago
Using bash:
~~~ shell
decode() {
printf '%b' "${1//%/\\x}"
}
8 years ago
~~~
Examples
--------
### Shell Bot
An interactive XMPP bot written in the shell:
~~~ shell
#!/bin/bash
set -o errexit
set -o nounset
8 years ago
set -o pipefail
trap cleanup EXIT
8 years ago
TMPDIR=$(mktemp -d)
in="$TMPDIR/stdin"
out="$TMPDIR/stdout"
mkfifo $in
mkfifo $out
cleanup() {
rm -rf $TMPDIR
}
decode() {
printf '%b' "${1//%/\\x}"
}
bot() {
while IFS=: read -r type status from to message; do
case "$type" in
m) ;;
p) decode "$type:$status:$from:$to" 1>&2
echo 1>&2
continue
;;
*) continue ;;
esac
USER="$(decode ${from#*/})"
MSG="$(decode ${message})"
case $MSG in
*"has set the subject to:"*) ;;
"sudo make me a sandwich")
echo "$USER: you're a sandwich"
;;
sudo*)
echo "I'm sorry, $USER. I'm afraid I can't do that."
;;
uptime)
uptime
;;
exit)
echo "exiting ..."
exit 0
;;
*)
echo "$MSG"
;;
esac
8 years ago
done < $out
}
bot > $in &
xmppipe "$@" <$in >$out
~~~
### SSH over XMPP
8 years ago
See [examples/ssh-over-xmpp](https://github.com/msantos/xmppipe/blob/master/examples/ssh-over-xmpp):
8 years ago
~~~ shell
8 years ago
# Server: has access to the destination SSH server
# ssh-over-xmpp server <conference> <IP address> <port>
ssh-over-xmpp server sshxmpp 1.2.3.4 22
## Client: has access to the XMPP server
ssh -o ProxyCommand="ssh-over-xmpp client sshxmpp" 127.0.0.1
~~~
8 years ago
### Stream Events from Riemann
This example will stream events from a query to an XMPP MUC using
[Riemann's](https://github.com/riemann/riemann) SSE interface. The events
are written to a named pipe to avoid buffering.
~~~ shell
8 years ago
mkfifo riemann
curl -s --get --data subscribe=true \
--data-urlencode 'query=(service ~= "^example")' \
http://example.com:80/index < /dev/null > riemann &
xmppipe --verbose --verbose \
--output "muc" --discard --subject "riemann events" < riemann
8 years ago
~~~
### Mirror a terminal session using script(1)
* user
~~~ shell
#!/bin/bash
MUC=console
TMPDIR=$(mktemp -d)
FIFO=$TMPDIR/console
mkfifo $FIFO
stty cols 80 rows 24
(cat $FIFO | xmppipe --resource user --output $MUC -x) > /dev/null 2> $TMPDIR/stderr &
script -q -f $FIFO
~~~
* viewers
~~~ shell
#!/bin/bash
decode() {
printf '%b' "${1//%/\\x}"
}
stty cols 80 rows 24
xmppipe --resource viewer --output console --base64 | \
while IFS=: read x s f t m; do
[ "$m" = "m" ] && decode $5
done
~~~
8 years ago
8 years ago
### Mirror a terminal session to a web page
8 years ago
Environment Variables
---------------------
* XMPPIPE_USERNAME: XMPP jid
* XMPPIPE_PASSWORD: XMPP password
Format
------
Each message is terminated by a new line. Message fields are separated by
":" and percent encoded.
### Presence
p:<available|unavailable>:<to jid>:<from jid>
Example:
p:available:test@muc.example.com/xmppipe:occupant@example.com/1234
8 years ago
### Message
m:<chat|groupchat>:<from jid>:<to jid>:<message body>
Example:
m:groupchat:test@muc.example.com/mobile:user1@example.com/1234:Hello
m:chat:user1@example.com/mobile:user2@example.com:Message%20goes%20here
8 years ago
Compatibility
-------------
Tested with ejabberd and mongooseim.
7 years ago
License
-------
Copyright (c) 2015-2017, Michael Santos <michael.santos@gmail.com>
7 years ago
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
8 years ago
TODO
----
* support [XEP-0384: OMEMO Encryption](https://xmpp.org/extensions/xep-0384.html)
7 years ago
* support alternative input modes
7 years ago
Add a command line argument to enable various input modes. The default
mode converts stdin to a message body.
"formatted" mode takes the same input as the output. For example,
to send a chat message:
echo 'm:chat:user1@example.com/mobile:user2@example.com:Message%20goes%20here' | xmppipe
A "raw" mode could also be added: XML input/output.