h3-cli is a convenient CLI (command-line interface) for accessing the Horizon3.ai API. The Horizon3.ai API provides programmatic access to a subset of functionality available through the Horizon3.ai Portal. At a high level, the API allows you to:
- schedule an autonomous pentest
- download and run NodeZero™
- monitor the status of a pentest while it is running
- retrieve a pentest report after it's complete
The API can be used for a variety of use cases such as scheduling periodic assessments of your environment or kicking off a pentest as part of a continuous integration build pipeline.
The steps below will get you up and running quickly with h3-cli. These instructions were tested on macOS and Linux machines, and generally should work on any POSIX-compliant system with bash support.
If you plan to run internal pentests using h3-cli, you should install h3-cli on the same Docker Host where you launch NodeZero.
It is assumed you already have an account with Horizon3.ai. If not, sign up at https://portal.horizon3ai.com/.
An API key is required to access the H3 API. You can create one in the Portal under the User -> Account Settings menu.
When creating an API key you must assign it a role that controls its permissions. The available roles are:
- User: Basic read/write permissions. The API key can run pentests and read results.
- Read-only: The API key can read pentest results, but cannot run pentests.
- NodeZero Runner: A specialized, heavily restricted role designed specifically for NodeZero Runners.
We recommend the User role if you're testing out h3-cli and want to experiment with all its features. After that, you may want to use more restrictive permissions, based on your use case. For example, if you only want to use h3-cli to set up a NodeZero Runner, we recommend using the NodeZero Runner role.
You can easily manage multiple API keys within the same h3-cli install. Learn more here.
❗ Keep your API key secure, as anyone with your API key can access your H3 account. Think of an API key as
a username + password rolled into one. Anyone with the API key can access your account from anywhere. h3-cli
will store your API key under the $HOME/.h3
directory. This directory is created during installation and
configured with permissions such that only you can read or write to it.
Install the h3-cli git repo on your machine by executing the following git command within a shell/terminal session.
git clone https://github.com/horizon3ai/h3-cli
This will create a new directory, h3-cli
, and download the contents of the repo to it. The h3-cli
directory
will be created in the directory where you run the git command. You can install h3-cli anywhere on the filesystem.
If you don't have git, you can download the repo as a zip archive from the menu above, and unzip it anywhere on the filesystem.
Run the following commands to install and configure h3-cli. Substitute your-api-key-here
with your actual API key.
cd h3-cli
bash install.sh your-api-key-here
The install script will install dependencies (jq) and create your default h3-cli profile under the $HOME/.h3
directory.
Your API key is stored in your h3-cli profile. The directory and profile permissions are restricted so that no other
users (besides yourself) can read or write to it.
The install script will ask you to edit your shell profile ($HOME/.bash_profile
or $HOME/.bash_login
or $HOME/.profile
, depending
on your operating system) to set the following environment variables:
H3_CLI_HOME
: this environment variable is used by h3-cli to locate itself and its supporting files.PATH
: this environment variable specifies the directories to be searched to find a shell command.
After updating your shell profile, re-login or restart your shell session to pick up the profile changes, then verify you can invoke h3 by running it from the command prompt:
h3
If everything's installed correctly, you should see the h3-cli help text.
We release new features, bug fixes, and other updates for the h3-cli every month. Upgrade your installation using one of the methods below.
As of June, 2023, you can use the h3 upgrade
command to upgrade to the latest version of h3-cli.
If you get an ERROR: unrecognized command: "upgrade"
, then you are on a previous version of h3-cli that does not
support the upgrade command. Use one of the methods below to upgrade h3-cli.
Run this command from h3-cli's parent directory (i.e. the directory that contains the h3-cli/
directory):
curl https://raw.githubusercontent.com/horizon3ai/h3-cli/public/easy_install.sh | bash
If you used git clone
to install the repo, then simply run git pull
to install the latest version.
If you downloaded the repo as a zip file, then re-download the zip file and unzip it to the same location (in other words replace your existing h3-cli installation with the new zip).
As of June, 2023, you can view your current version of h3-cli via:
h3 version
You can view the full history of versions and release notes via:
h3 version -v
Run the following command to verify connectivity with the API.
h3 hello-world
You should see the response:
{
"data": {
"hello": "world!"
}
}
❗️ If you are getting an error response, please contact H3 via the chat icon in the Horizon3.ai Portal.
The command below will return the list of pentests in your account, most recent first.
h3 pentests
To filter for pentests that match a given search term, pass the search term as a parameter:
h3 pentests sample
To query the most recent pentest in your account:
h3 pentest
To query any pentest in your account, pass the op_id
of the pentest as a parameter:
h3 pentest your-op-id-here
Several h3-cli commands will use the most recent pentest as the default,
unless an op_id
is passed as a parameter.
The terms "op" and "pentest" are often used interchangeably.
Running a pentest requires specifying an op template. An op template specifies a full pentest configuration, which includes scope, attack parameters, and other (optional) configuration.
Horizon3.ai provides new users with a default op template named Default 1 - Recommended
. This template is always
up-to-date with our latest attack parameters and recommended configuration. The default template does not define a scope,
in which case NodeZero will use Intelligent Scope - NodeZero's host subnet will provide the initial scope, and it will expand
organically during the pentest as more hosts and subnets are discovered. For more information on Intelligent Scope and other
deployment options, visit our product documentation.
For experienced users, custom op template(s) may be created via the Horizon3.ai Portal. To create a custom op template, walk through the Run a Pentest modal until you see the option to customize the pentest configuration. The op template can be created without actually running the pentest.
To provision a pentest using the default op template and Intelligent Scope:
h3 run-pentest
The JSON response contains the details for the newly created pentest.
You can verify the pentest is provisioning by checking your Horizon3.ai Portal,
or by running h3 pentest
.
There are several ways to specify additional parameters when creating pentests. For more information see additional examples here.
❗ WAIT! YOU'RE NOT DONE!
For internal pentests (which are the default), additional steps are required before the pentest will begin running. See the next section about downloading and running NodeZero in order to complete the initiation of your pentest.
If you are running an external pentest, NodeZero is launched for you automatically in the H3 cloud as part of
h3 run-pentest
, in which case there are no additional steps on your end to initiate the pentest.
❗ ️The following step applies to internal pentests only; for external pentests, NodeZero is launched for you automatically in the H3 cloud.
After creating an internal pentest, you then have to run our NodeZero container on a Docker Host inside your network. This is done by running the NodeZero Launch Script on your Docker Host.
To run the NodeZero Launch Script for your most recently created pentest:
h3 run-nodezero
YOUR PENTEST HAS BEEN LAUNCHED! Assuming all commands ran without error, then you have successfully created and launched your pentest. You should see output from the NodeZero Launch Script being logged to the console. The script will first verify your system is compatible with NodeZero before downloading and running it. When the pentest is complete, NodeZero will automatically shut itself down.
NodeZero is a Docker container. You can view it using docker ps
. The container name will be of the form n0-xxxx
.
After your pentest has finished, use the following command to download a zip file containing all PDF and CSV reports for the most recently created pentest:
h3 pentest-reports
The above command will download the zip file to pentest-reports-{op_id}.zip
in the current directory.
- Automated NodeZero deployment using a NodeZero Runner. Learn how to use a NodeZero Runner to deploy NodeZero on your Docker Host automatically, without having to manually copy+paste the NodeZero Launch Script.
- Automated scheduling. Learn how to run pentests automatically on a regular schedule, for example once a week or once a month.
- Auto-injected credentials. Learn how to automatically inject credentials into a regularly scheduled pentest using a NodeZero Runner.
- Monitoring pentests. Learn how to monitor pentests using h3-cli.
- Paginating results. Learn how to paginate through large result sets using h3-cli.
- JSON Parsing using
jq
. Learn how to leverage the power ofjq
to parse JSON responses from h3-cli.jq
can parse specific fields, print the structure of a response, and even transform a JSON response to CSV.
Authentication happens seamlessly and automatically when you invoke the h3
command.
There's nothing explicit you need to do to authenticate. This section documents the
underlying mechanics.
h3-cli reads your H3_API_KEY
from your h3-cli profile (under $HOME/.h3
) to authenticate
to the Horizon3.ai API and establish a (temporary) session. The session token (a JWT) is
cached under $HOME/.h3
. The session token expires after 1 hour, at which point h3-cli will
automatically re-authenticate and re-establish a session.
You can explicitly authenticate using the following command:
h3 auth
The above command will output the session token (and also cache it under $HOME/.h3
).
If you already have an established (non-expired) session token, h3 auth
will continue to use
that session token rather than re-authenticate.
If you want to force h3-cli to re-authenticate, use the force
option:
h3 auth force
You can manage multiple h3-cli authentication profiles under the same $HOME/.h3
directory.
Each h3-cli profile has its own API key.
When you first install h3-cli it will automatically create an initial profile named default
with the API key you provided to install.sh
.
If you wish to create another profile with a different API key, use the following command:
h3 save-profile my-profile {api-key}
This will create a profile named my-profile
under $HOME/.h3
for the given {api_key}
.
To activate the profile in your current shell session, use the following command (note the leading dot .
):
. h3 profile my-profile
You can verify the currently active profile using h3 profile
, and view details about its API key using h3 whoami
:
h3 profile
h3 whoami
You can save multiple API keys under different h3-cli profiles and switch between them as needed using the command above.
For example, to switch back to the default
profile:
. h3 profile default
To view the list of h3-cli profiles under your $HOME/.h3
directory:
h3 profiles
You can delete a profile from your $HOME/.h3
directory using:
h3 delete-profile {name}
This will remove the profile named {name}
and its API key from your $HOME/.h3
directory on the local machine.
Note that it will NOT revoke the API key; it only deletes it from the local machine. You can revoke the API key from the Portal.
This section contains additional examples for running pentests using h3-cli.
The simplest way to provision a pentest is to use the default op template and Intelligent Scope:
h3 run-pentest
To provision a pentest AND launch NodeZero on the local machine (for internal pentests only):
h3 run-pentest-and-nodezero
Note that this only applies to internal pentests. For external pentests, NodeZero is launched for you automatically in the H3 cloud as part of h3 run-pentest
.
If you happen to run
h3 run-pentest-and-nodezero
for an external pentest, it will simply skip the part where it downloads and runs NodeZero, since that is handled automatically in the H3 cloud.
To run a pentest using a custom op template, specify it as a parameter to schedule_op_template.graphql:
h3 run-pentest '{"op_template_name":"your-op-template-here"}'
To run a pentest using the default op template but assign it a name of your choosing, use the optional op_name
parameter:
h3 run-pentest '{"op_name":"your-op-name-here"}'
To run a pentest using the default op template but specify its name and scope, use the optional schedule_op_form
parameter:
h3 run-pentest '{"schedule_op_form":{"op_name":"your-op-name-here", "op_param_max_scope": "192.168.0.0/24"}}'
Note that
h3 run-pentest
andh3 run-pentest-and-nodezero
accept all the same optional parameters.
To run a pentest and assign it to a NodeZero Runner named my-nodezero-runner
:
h3 run-pentest '{"schedule_op_form":{"op_name":"Pentest created via h3-cli and launched via runner", "runner_name":"my-nodezero-runner"}}'
If you have an op template configured for your external pentest:
h3 run-pentest '{"op_template_name":"your-op-template-here"}'
If you do NOT have an op template, you can run an external pentest by first looking up your Asset Group's uuid via h3 asset-groups
:
h3 asset-groups
Then use the command below to run an external pentest against that Asset Group. Substitute your Asset Group's uuid for {your-asset-group-uuid}
:
h3 run-pentest '{"schedule_op_form": {"op_type": "ExternalAttack", "asset_group_uuid": "{your-asset-group-uuid}"}}'
The Horizon3.ai API is powered by GraphQL. In addition to this CLI document, relevant documentation includes:
h3-cli provides a simple mechanism to run your own GraphQL queries. First you define the
GraphQL query in a file (typically with a .graphql
extension, although that is not required).
Then pass the file to h3 gql
:
h3 gql {your-query-file}
For example, define the following in a file named my_session.graphql
:
query {
session_user_account {
email
name
company_name
}
}
Then run:
h3 gql ./my_session.graphql
You should see the raw JSON response from the GraphQL server. You can pretty-print the JSON response using jq:
h3 gql ./my_session.graphql | jq .
Important! You must specify the path to the graphql file (full or relative, e.g. ./my_session.graphql
instead of just my_session.graphql
),
otherwise you risk colliding with graphql files that h3-cli uses internally.
GraphQL queries can also define parameters, which are passed to h3 gql
as a JSON object.
For example, define the following in a file named my_pentest.graphql
:
query q($op_id: String!) {
pentest(op_id:$op_id) {
op_id
name
state
}
}
In this example, $op_id
is a parameter that must be provided in order to run the query.
The parameter is passed to the query within a JSON object:
h3 gql ./my_pentest.graphql '{"op_id":"your-op-id-here"}' | jq .
Substitute
your-op-id-here
with an actualop_id
.