Skip to content

Commit

Permalink
Init commit
Browse files Browse the repository at this point in the history
  • Loading branch information
faloker committed Feb 22, 2020
0 parents commit e468aa6
Show file tree
Hide file tree
Showing 11 changed files with 587 additions and 0 deletions.
121 changes: 121 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# vscode
.vscode

# venv
venv*
5 changes: 5 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM python:alpine

RUN pip install wallarm-fast-cli

ENTRYPOINT [ "fast-cli" ]
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2018 faloker

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Description
Wallarm FAST CLI - A simple command line interface for [Wallarm FAST](https://wallarm.com/products/fast/). For now, this tool can be used in CI system to create test runs and retrieve detected vulnerabilities.

# Installation
To install the latest release from PyPI, you can run the following command:
`pip install wallarm-fast-cli`
Also, you can use docker image:
`docker pull faloker/wallarm-fast-cli`

# Usage
```
Usage: fast-cli [OPTIONS] COMMAND [ARGS]...
Wallarm FAST CLI - A simple command line interface for Wallarm FAST.
Options:
--uuid TEXT You personal UUID to authorize API calls. Defaults to the
value of the env variable WALLARM_UUID.
--secret TEXT You personal secret key to authorize API calls. Defaults to
the value of the env variable WALLARM_SECRET.
--help Show this message and exit.
Commands:
check Check that credentials (UUID and Secret key) are valid.
create Create a new test run with provided parameters.
report Get all findings from test run by id. Findings will be in JSON
format.
```

Main purpose of this tool is to create test runs from CI system (i.e. Jenkins), it can be done with create command:
```
Usage: fast-cli create [OPTIONS]
Options:
-n, --name TEXT Test run name. [required]
-N, --node TEXT Node name for test execution. No cloud, only
node. [required]
-D, --desc TEXT Short description. Defaults to empty decription.
-P, --policy TEXT Policy name to apply.
-T, --tags TEXT Comma-separated tags to test run.
-Rt, --rps-total INTEGER The max number of concurrent requests.
-Rb, --rps-per-url INTEGER The max number of concurrent requests for one
baseline (unique url).
--track / --no-track If set, then test execution will be tracked and
all findings will be exported at the end.
-o, --out-file TEXT Save report to the file. Otherwise, the results will
be output to stdout.
--help Show this message and exit.
```
Example of command to create test run:
`fast-cli create -n awesome_run -N super_node -P my_policy -T fast,cli,test -Rt 200 -Rb 20`
1 change: 1 addition & 0 deletions fastcli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__name__ = "wallarm-fast-cli"
146 changes: 146 additions & 0 deletions fastcli/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import sys
import os
from time import sleep

import click

from fastcli.fast_helper import FASTHelper
from fastcli.log import console
from fastcli.helpers import fast_error_handler


@click.group(
help="Wallarm FAST CLI - A simple command line interface for Wallarm FAST."
)
@click.option(
"--uuid",
default="",
envvar="WALLARM_UUID",
type=str,
help="You personal UUID to authorize API calls. Defaults to the value of the env variable WALLARM_UUID.",
)
@click.option(
"--secret",
default="",
envvar="WALLARM_SECRET",
type=str,
help="You personal secret key to authorize API calls. Defaults to the value of the env variable WALLARM_SECRET.",
)
@click.pass_context
def cli(ctx, uuid, secret):
ctx.obj = FASTHelper(wallarm_uuid=uuid, wallarm_secret=secret)


@cli.command("create", short_help="Create a new test run with provided parameters.")
@click.option("--name", "-n", required=True, help="Test run name.")
@click.option(
"--node",
"-N",
required=True,
help="Node name for test execution. No cloud, only node.",
)
@click.option(
"--desc", "-D", default="", help="Short description. Defaults to empty decription."
)
@click.option("--policy", "-P", help="Policy name to apply.")
@click.option("--tags", "-T", help="Comma-separated tags to test run.")
@click.option(
"--rps-total", "-Rt", type=int, help="The max number of concurrent requests."
)
@click.option(
"--rps-per-url",
"-Rb",
type=int,
help="The max number of concurrent requests for one baseline (unique url).",
)
@click.option(
"--track/--no-track",
default=True,
is_flag=True,
help="If set, then test execution will be tracked and all findings will be exported at the end.",
)
@click.option(
"--out-file",
"-o",
help="Save report to file. Otherwise, the results will be output to stdout.",
)
@click.pass_obj
def create(
fast, name, desc, tags, node, policy, rps_total, rps_per_url, track, out_file
):
with fast_error_handler():
test_run = fast.create_test_run(
name, desc, tags, node, policy, rps_total, rps_per_url
)

console.info(
"Name: {}\nState: {}\nID: {}".format(
test_run["name"], test_run["state"], test_run["id"]
)
)

if track:
while True:
with fast_error_handler():
tr = fast.fetch_test_run(test_run["id"])

done = tr["baseline_check_all_terminated_count"]
left = tr["baseline_count"]
state = tr["state"]

if left:
console.info(
"Auditing {}/{} [ {} % ]".format(
done, left, round(done / left, 2) * 100
)
)
else:
console.info("Waiting for baselines...")

if state != "running":
break
else:
sleep(120)

with fast_error_handler():
report = fast.fetch_vulns_from_test_run(test_run["id"])

if out_file:
with click.open_file(out_file, "w+") as f:
f.write(report)
else:
print(report)


@cli.command(
"report",
short_help="Get all findings from test run by id. Findings will be in JSON format.",
)
@click.option(
"--test-run-id", "-id", required=True, help="Test run id to get issues from."
)
@click.option(
"--out-file",
"-o",
help="Save report to file. Otherwise, the results will be output to stdout.",
)
@click.pass_obj
def report(fast, test_run_id, out_file):
with fast_error_handler():
report = fast.fetch_vulns_from_test_run(test_run_id)

if out_file:
with click.open_file(out_file, "w+") as f:
f.write(report)
else:
print(report)


@cli.command(
"check", short_help="Check that credentials (UUID and Secret key) are valid."
)
@click.pass_obj
def check(fast):
with fast_error_handler():
if fast.get_client_id():
console.info("Credentials are valid.")
6 changes: 6 additions & 0 deletions fastcli/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class FASTError(Exception):
"""Generic exception for FAST CLI."""

def __init__(self, message, extra=None):
super(FASTError, self).__init__(message)
self.extra = extra
Loading

0 comments on commit e468aa6

Please sign in to comment.