Making PoC follow spec regarding to the "kapow route" command and, incidentally creating a new "kapow server" command.

This commit is contained in:
Roberto Abdelkader Martínez Pérez
2019-06-04 14:40:01 +02:00
parent e4cbb96cf4
commit 96739189f1
9 changed files with 93 additions and 98 deletions
-69
View File
@@ -1,69 +0,0 @@
#!/usr/bin/env python
#
# Copyright 2019 Banco Bilbao Vizcaya Argentaria, S.A.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import sys
import click
import requests
@click.group()
def kroute():
pass
@kroute.command()
@click.option("-c", "--command", nargs=1)
@click.option("-e", "--entrypoint", default="/bin/sh -c")
@click.option("-X", "--method", default="GET")
@click.option("--url", envvar='KAPOW_URL')
@click.argument("url_pattern", nargs=1)
@click.argument("command_file", required=False)
def add(url_pattern, entrypoint, command, method, url, command_file):
if command:
# Command is given inline
source = command
elif command_file is None:
# No command
source = ""
elif command_file == '-':
# Read commands from stdin
source = sys.stdin.read()
else:
# Read commands from a file
with open(command_file, 'r', encoding='utf-8') as handler:
source = handler.read()
response = requests.post(f"{url}/routes",
json={"method": method,
"url_pattern": url_pattern,
"entrypoint": entrypoint,
"command": source})
response.raise_for_status()
print(response.json())
@kroute.command()
@click.option("--url", envvar='KAPOW_URL')
@click.argument("route-id")
def remove(route_id, url):
response = requests.delete(f"{url}/routes/{route_id}")
response.raise_for_status()
print(response.json())
if __name__ == '__main__':
kroute()
+1 -1
View File
@@ -16,4 +16,4 @@
# limitations under the License. # limitations under the License.
# #
kroute add -X POST '/eval' -c '$($(request /body) | response /stream)' kapow route add -X POST '/eval' -c '$($(request /body) | response /stream)'
+1 -1
View File
@@ -16,4 +16,4 @@
# limitations under the License. # limitations under the License.
# #
kroute add -X GET '/list/{ip}' -c 'nmap -sL $(request /match/ip) | response /body' kapow route add -X GET '/list/{ip}' -c 'nmap -sL $(request /match/ip) | response /body'
+9 -9
View File
@@ -16,26 +16,26 @@
# limitations under the License. # limitations under the License.
# #
kroute add /list/files -c 'ls -la $(request /param/path) | response /body' kapow route add /list/files -c 'ls -la $(request /param/path) | response /body'
kroute add /list/processes -c 'ps -aux | response /body' kapow route add /list/processes -c 'ps -aux | response /body'
kroute add /show/cpuinfo -c 'response /body < /proc/cpuinfo' kapow route add /show/cpuinfo -c 'response /body < /proc/cpuinfo'
kroute add /show/memory -c 'free -m | response /body' kapow route add /show/memory -c 'free -m | response /body'
kroute add /show/disk -c 'df -h | response /body' kapow route add /show/disk -c 'df -h | response /body'
kroute add /show/connections -c 'ss -pluton | response /body' kapow route add /show/connections -c 'ss -pluton | response /body'
kroute add /show/mounts -c 'mount | response /body' kapow route add /show/mounts -c 'mount | response /body'
kroute add /tail/dmesg - <<-'EOF' kapow route add /tail/dmesg - <<-'EOF'
response /header/Content-Type text/plain response /header/Content-Type text/plain
dmesg -w | response /stream dmesg -w | response /stream
EOF EOF
kroute add /tail/journal - <<-'EOF' kapow route add /tail/journal - <<-'EOF'
response /header/Content-Type text/plain response /header/Content-Type text/plain
journalctl -f | response /stream journalctl -f | response /stream
EOF EOF
+3 -3
View File
@@ -16,11 +16,11 @@
# limitations under the License. # limitations under the License.
# #
kroute add -X POST --entrypoint '/bin/zsh -c' '/convert/{from}/{to}' - <<-'EOF' kapow route add -X POST --entrypoint '/bin/zsh -c' '/convert/{from}/{to}' - <<-'EOF'
pandoc --from=$(request /match/from) \ pandoc --from=$(request /match/from) \
--to=$(request /match/to) \ --to=$(request /match/to) \
--output=>(response /body) \ --output=>(response /body) \
=(request /body) =(request /body)
EOF EOF
kroute add -X GET '/formats/input' -c 'pandoc --list-input-formats | response /body' kapow route add -X GET '/formats/input' -c 'pandoc --list-input-formats | response /body'
kroute add -X GET '/formats/output' -c 'pandoc --list-output-formats | grep -v pdf | response /body' kapow route add -X GET '/formats/output' -c 'pandoc --list-output-formats | grep -v pdf | response /body'
+2 -2
View File
@@ -16,5 +16,5 @@
# limitations under the License. # limitations under the License.
# #
kroute add -X POST --entrypoint ./topdf '/editor/pdf' kapow route add -X POST --entrypoint ./topdf '/editor/pdf'
kroute add / -c 'response /header/Content-Type text/html && response /body < pdfeditor.html' kapow route add / -c 'response /header/Content-Type text/html && response /body < pdfeditor.html'
+3 -3
View File
@@ -16,7 +16,7 @@
# limitations under the License. # limitations under the License.
# #
kroute add / - <<-'EOF' kapow route add / - <<-'EOF'
response /header/Content-Type text/html response /header/Content-Type text/html
response /body <<-HTML response /body <<-HTML
<html> <html>
@@ -27,7 +27,7 @@ kroute add / - <<-'EOF'
HTML HTML
EOF EOF
kroute add /save/magnet -e '/bin/bash -c' - <<-'EOF' kapow route add /save/magnet -e '/bin/bash -c' - <<-'EOF'
link=$(request /param/link) link=$(request /param/link)
[ -z $link ] && response /status 400 && exit 0 [ -z $link ] && response /status 400 && exit 0
@@ -40,4 +40,4 @@ kroute add /save/magnet -e '/bin/bash -c' - <<-'EOF'
response /header/Location /torrent/list response /header/Location /torrent/list
EOF EOF
kroute add /torrent/list -c 'response /body "Not Implemented Yet"' kapow route add /torrent/list -c 'response /body "Not Implemented Yet"'
+73 -9
View File
@@ -26,6 +26,9 @@ import shlex
import sys import sys
from aiohttp import web, StreamReader from aiohttp import web, StreamReader
import click
import requests
log = logging.getLogger('kapow') log = logging.getLogger('kapow')
@@ -281,22 +284,21 @@ async def delete_route(request):
######################################################################## ########################################################################
async def run_init_script(app): async def run_init_script(app, scripts):
""" """
Run the init script if given, then wait for the shell to finish. Run the init script if given, then wait for the shell to finish.
""" """
if len(sys.argv) == 1: if not scripts:
# No script given # No script given
cmd = "/bin/bash" cmd = "/bin/bash"
elif len(sys.argv) == 2:
cmd = f"/bin/bash --init-file {sys.argv[1]}"
else: else:
print(f"Usage: {sys.argv[0]} <init-script>") filenames = " ".join(shlex.quote(f) for f in scripts)
os._exit(1) cmd = f"/bin/bash --init-file <(cat {filenames})"
shell_task = await asyncio.create_subprocess_shell( shell_task = await asyncio.create_subprocess_shell(
cmd, cmd,
executable="/bin/bash",
env={**os.environ, env={**os.environ,
"KAPOW_URL": "http://localhost:8080/kapow" "KAPOW_URL": "http://localhost:8080/kapow"
}) })
@@ -308,11 +310,10 @@ async def run_init_script(app):
async def start_background_tasks(app): async def start_background_tasks(app):
loop = asyncio.get_running_loop() loop = asyncio.get_running_loop()
app["debug_tasks"] = loop.create_task(run_init_script(app)) app["debug_tasks"] = loop.create_task(run_init_script(app, app["scripts"]))
def kapow(): def start_kapow_server(scripts):
"""Start aiohttp app."""
app = web.Application(client_max_size=1024**3) app = web.Application(client_max_size=1024**3)
app.add_routes([ app.add_routes([
web.get('/kapow/routes', get_routes), web.get('/kapow/routes', get_routes),
@@ -322,9 +323,72 @@ def kapow():
# web.post('/kapow/connections/{id}/{field:.*}', append_field), # web.post('/kapow/connections/{id}/{field:.*}', append_field),
web.put('/kapow/connections/{id}/{field:.*}', set_field), web.put('/kapow/connections/{id}/{field:.*}', set_field),
]) ])
app["scripts"] = scripts
app.on_startup.append(start_background_tasks) app.on_startup.append(start_background_tasks)
web.run_app(app) web.run_app(app)
########################################################################
# Command Lineagement #
########################################################################
@click.group()
@click.pass_context
def kapow(ctx):
"""Start aiohttp app."""
pass
@kapow.command()
@click.argument("scripts", nargs=-1)
def server(scripts):
start_kapow_server(scripts)
@kapow.group()
def route():
pass
@route.command()
@click.option("-c", "--command", nargs=1)
@click.option("-e", "--entrypoint", default="/bin/sh -c")
@click.option("-X", "--method", default="GET")
@click.option("--url", envvar='KAPOW_URL')
@click.argument("url_pattern", nargs=1)
@click.argument("command_file", required=False)
def add(url_pattern, entrypoint, command, method, url, command_file):
if command:
# Command is given inline
source = command
elif command_file is None:
# No command
source = ""
elif command_file == '-':
# Read commands from stdin
source = sys.stdin.read()
else:
# Read commands from a file
with open(command_file, 'r', encoding='utf-8') as handler:
source = handler.read()
response = requests.post(f"{url}/routes",
json={"method": method,
"url_pattern": url_pattern,
"entrypoint": entrypoint,
"command": source})
response.raise_for_status()
print(response.json())
@route.command()
@click.option("--url", envvar='KAPOW_URL')
@click.argument("route-id")
def remove(route_id, url):
response = requests.delete(f"{url}/routes/{route_id}")
response.raise_for_status()
print(response.json())
if __name__ == '__main__': if __name__ == '__main__':
kapow() kapow()
+1 -1
View File
@@ -470,7 +470,7 @@ You can run it by ...
Any compliant implementation of Kapow! must provide these commands: Any compliant implementation of Kapow! must provide these commands:
### `kapow` ### `kapow server`
This implements the server, XXX This implements the server, XXX