---
# SPDX-FileCopyrightText: the secureCodeBox authors
#
# SPDX-License-Identifier: Apache-2.0

title: "ADR-0003: How can we introduce a mechanism to start specialized scans on the results of previous scans?"
sidebar_label: "ADR-0003"
---
# ADR-0003: How can we introduce a mechanism to start specialized scans on the results of previous scans?

| <!-- -->       | <!-- --> |
|----------------|----------|
| **Status**:    | ACCEPTED |
| **Date**:      | 2020-05-20 |
| **Author(s)**: | Jannik Hollenbach [jannick.hollenbach@iteratec.com](mailto:jannick.hollenbach@iteratec.com), Robert Seedorff [Robert.Seedorff@iteratec.com](mailto:Robert.Seedorff@iteratec.com), Sven Strittmatter [sven.strittmatter@iteratec.com](mailto:Sven.Strittmatter@iteratec.com) |

## Context

### Status Quo

Currently scans by the secureCodeBox are single focused on a specific tool. Combining multiple scans requires manual or scripting by the user to use the results of a scan (e.g. Nmap) as a input for another scanner (e.g. SSLyze)

### Problem and Question

How can the results of a scan be used to automatically configure subsequent specialized scans for identified targets.

In general we want to describe cascading scans like:

```text
+--------+             +--------+             +--------+
| scan 1 |-- result -->| scan 2 |-- result -->| scan 3 |
+--------+             +--------+       |     +--------+
                                        |
                                        |     +--------+
                                        +---->| scan 4 |
                                              +--------+
```

A concrete example:

```text
+----------------+         +-----------------+               +-----------+
|    <<nmap>>    |         |     <<nmap>>    |               |  <<SSL>>  |
| find all hosts |-- IP -->| find open ports |-- port 443 -->| check TLS |
+----------------+         +-----------------+      |        +-----------+
                                                    |
                                                    |        +-------------+
                                                    |        |  <<nikto>>  |
                                                    +------->| check HTTPd |
                                                             +-------------+
```

The solution should fulfill the following criteria:

- The "rules" used to describe which subsequent scans can be executed should be modular, so that they can be packaged together with the scan types.
- It should be possible for a user to select which scan rules should be applied
- Protections should be in place to ensure that the clusters are not completely overwhelmed by these automatically created scans. Especially circular structures which create a infinite number of scans should be prevented.

## Decision

It was decided to implement these rules as Custom Resource Definitions (CRDs) in Kubernetes. This allows the Helm Charts of the scanners to package related rules for the scanner together with their ScanTypes.

### Defining CascadingRule

The so called "CascadingRules" consist of a "matches" section which contains one or multiple rules which are compared against findings. When a finding matches a rule the "scanSpec" section will then be used to create a new scan. To customize the scan to match the finding, the [mustache](https://github.com/janl/mustache.js) templating language
can be used to reference fields of the finding.

```yaml
apiVersion: "cascading.securecodebox.io/v1"
kind: CascadingRule
metadata:
  name: "tls-scans"
  labels:
    # Described how "invasive" the scan is.
    # Possible values: "invasive" or "non-invasive"
    # CascadingRules are considered "invasive" when the Scan they start actively sends out packages with attack payloads.
    securecodebox.io/invasive: non-invasive
    # Described the intensiveness level on a scanning and computational resource level.
    # Possible values: "ligh", "medium", "intense"
    # CascadingRules are considered more "intensive" when the Scan they start consumes lots of computational resources like RAM, CPU, or Network
    securecodebox.io/intensive: light
spec:
  matches:
    # CascadingRule triggers if a finding matches at least one of the anyOf matchers
    # With the first version of this implementation only anyOf would be supported.
    # If this turns out to be lacking and other operators (like `allOf` can be introduced without breaking changes)
    anyOf:
      # define an explicit "port" as finding and a given port number
      - category: "Open Port"
        attributes:
          port: 443
          service: "https"
      # define an "port service" finding (any port)
      - category: "Open Port"
        attributes:
          service: "https"
  scanSpec:
    name: "sslyze"
    parameters: ["--regular", "{{attributes.hostname}}"]
```

### Using CascadingRules

By default no cascading Rules will be used.

```yaml
# Nmap Scan without cascading rules
apiVersion: "execution.securecodebox.io/v1"
kind: Scan
metadata:
  name: "portscan-berlin-wifi"
  label:
    office: berlin
    vlan: wifi
spec:
  name: "nmap"
  parameters: ["-sV", "10.42.0.0/16"]
```

To enable cascading rules you need to specify a label selector to select
the cascading rules you’d like

```yaml
apiVersion: "execution.securecodebox.io/v1"
kind: Scan
metadata:
  name: "portscan-berlin-wifi"
  label:
    office: berlin
    vlan: wifi
spec:
  cascades:
    matchLabels:
      # Uses all CascadingRules in the namespace which are labelled as "non-invasive" and a intensiveness level of "light"
      securecodebox.io/invasive: non-invasive
      securecodebox.io/intensive: light
  name: "nmap"
  parameters: ["-sV", "10.42.0.0/16"]
```

To implicitly enable all cascading rules (not-recommended) a empty label
selector can be used

```yaml
apiVersion: "execution.securecodebox.io/v1"
kind: Scan
metadata:
  name: "portscan-berlin-wifi"
  label:
    office: berlin
    vlan: wifi
spec:
  cascades:
    # Uses all `CascadingRules` in the namespace
    matchLabels: {}
  name: "nmap"
  parameters: ["-sV", "10.42.0.0/16"]
```

The label selectors also allow the more powerful [matchExpression](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#set-based-requirement) selectors:

```yaml
apiVersion: "execution.securecodebox.io/v1"
kind: Scan
metadata:
  name: "example.com"
spec:
  scanType: nmap
  parameters:
    - -p22,80,443
    - example.com
  cascades:
    # Using matchExpression instead of matchLabels
    matchExpression:
      key: "securecodebox.io/intensive"
      operator: In
      # This select both light and medium intensity rules
      values: [light, medium]
```
