Making PoC follow spec regarding to the "kapow route" command and, incidentally creating a new "kapow server" command.
This commit is contained in:
@@ -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()
|
||||
@@ -16,4 +16,4 @@
|
||||
# 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)'
|
||||
|
||||
@@ -16,4 +16,4 @@
|
||||
# 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'
|
||||
|
||||
@@ -16,26 +16,26 @@
|
||||
# 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
|
||||
dmesg -w | response /stream
|
||||
EOF
|
||||
|
||||
kroute add /tail/journal - <<-'EOF'
|
||||
kapow route add /tail/journal - <<-'EOF'
|
||||
response /header/Content-Type text/plain
|
||||
journalctl -f | response /stream
|
||||
EOF
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
# 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) \
|
||||
--to=$(request /match/to) \
|
||||
--output=>(response /body) \
|
||||
=(request /body)
|
||||
EOF
|
||||
kroute 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/input' -c 'pandoc --list-input-formats | response /body'
|
||||
kapow route add -X GET '/formats/output' -c 'pandoc --list-output-formats | grep -v pdf | response /body'
|
||||
|
||||
@@ -16,5 +16,5 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
kroute add -X POST --entrypoint ./topdf '/editor/pdf'
|
||||
kroute add / -c 'response /header/Content-Type text/html && response /body < pdfeditor.html'
|
||||
kapow route add -X POST --entrypoint ./topdf '/editor/pdf'
|
||||
kapow route add / -c 'response /header/Content-Type text/html && response /body < pdfeditor.html'
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
kroute add / - <<-'EOF'
|
||||
kapow route add / - <<-'EOF'
|
||||
response /header/Content-Type text/html
|
||||
response /body <<-HTML
|
||||
<html>
|
||||
@@ -27,7 +27,7 @@ kroute add / - <<-'EOF'
|
||||
HTML
|
||||
EOF
|
||||
|
||||
kroute add /save/magnet -e '/bin/bash -c' - <<-'EOF'
|
||||
kapow route add /save/magnet -e '/bin/bash -c' - <<-'EOF'
|
||||
link=$(request /param/link)
|
||||
[ -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
|
||||
EOF
|
||||
|
||||
kroute add /torrent/list -c 'response /body "Not Implemented Yet"'
|
||||
kapow route add /torrent/list -c 'response /body "Not Implemented Yet"'
|
||||
|
||||
@@ -26,6 +26,9 @@ import shlex
|
||||
import sys
|
||||
|
||||
from aiohttp import web, StreamReader
|
||||
import click
|
||||
import requests
|
||||
|
||||
|
||||
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.
|
||||
|
||||
"""
|
||||
if len(sys.argv) == 1:
|
||||
if not scripts:
|
||||
# No script given
|
||||
cmd = "/bin/bash"
|
||||
elif len(sys.argv) == 2:
|
||||
cmd = f"/bin/bash --init-file {sys.argv[1]}"
|
||||
else:
|
||||
print(f"Usage: {sys.argv[0]} <init-script>")
|
||||
os._exit(1)
|
||||
filenames = " ".join(shlex.quote(f) for f in scripts)
|
||||
cmd = f"/bin/bash --init-file <(cat {filenames})"
|
||||
|
||||
shell_task = await asyncio.create_subprocess_shell(
|
||||
cmd,
|
||||
executable="/bin/bash",
|
||||
env={**os.environ,
|
||||
"KAPOW_URL": "http://localhost:8080/kapow"
|
||||
})
|
||||
@@ -308,11 +310,10 @@ async def run_init_script(app):
|
||||
|
||||
async def start_background_tasks(app):
|
||||
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():
|
||||
"""Start aiohttp app."""
|
||||
def start_kapow_server(scripts):
|
||||
app = web.Application(client_max_size=1024**3)
|
||||
app.add_routes([
|
||||
web.get('/kapow/routes', get_routes),
|
||||
@@ -322,9 +323,72 @@ def kapow():
|
||||
# web.post('/kapow/connections/{id}/{field:.*}', append_field),
|
||||
web.put('/kapow/connections/{id}/{field:.*}', set_field),
|
||||
])
|
||||
app["scripts"] = scripts
|
||||
app.on_startup.append(start_background_tasks)
|
||||
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__':
|
||||
kapow()
|
||||
|
||||
+1
-1
@@ -470,7 +470,7 @@ You can run it by ...
|
||||
Any compliant implementation of Kapow! must provide these commands:
|
||||
|
||||
|
||||
### `kapow`
|
||||
### `kapow server`
|
||||
|
||||
This implements the server, XXX
|
||||
|
||||
|
||||
Reference in New Issue
Block a user