github.com/khulnasoft-lab/kube-bench@v0.2.1-0.20240330183753-9df52345ae58/docs/controls.md (about)

     1  # Test and config files
     2  
     3  `kube-bench` runs checks specified in `controls` files that are a YAML 
     4  representation of the CIS Kubernetes Benchmark checks (or other distribution-specific hardening guides). 
     5  
     6  ## Controls
     7  
     8  `controls` is a YAML document that contains checks that must be run against a 
     9  specific Kubernetes node type, master or node and version.
    10  
    11  `controls` is the fundamental input to `kube-bench`. The following is an example 
    12  of a basic `controls`:
    13  
    14  ```yml
    15  ---
    16  controls:
    17  id: 1
    18  text: "Master Node Security Configuration"
    19  type: "master"
    20  groups:
    21  - id: 1.1
    22    text: API Server
    23    checks:
    24      - id: 1.1.1
    25        text: "Ensure that the --allow-privileged argument is set (Scored)"
    26        audit: "ps -ef | grep kube-apiserver | grep -v grep"
    27        tests:
    28        bin_op: or
    29        test_items:
    30        - flag: "--allow-privileged"
    31          set: true
    32        - flag: "--some-other-flag"
    33          set: false
    34        remediation: "Edit the /etc/kubernetes/config file on the master node and
    35          set the KUBE_ALLOW_PRIV parameter to '--allow-privileged=false'"
    36        scored: true
    37  - id: 1.2
    38    text: Scheduler
    39    checks:
    40      - id: 1.2.1
    41        text: "Ensure that the --profiling argument is set to false (Scored)"
    42        audit: "ps -ef | grep kube-scheduler | grep -v grep"
    43        tests:
    44          bin_op: and
    45          test_items:
    46            - flag: "--profiling"
    47              set: true
    48            - flag: "--some-other-flag"
    49              set: false
    50        remediation: "Edit the /etc/kubernetes/config file on the master node and
    51          set the KUBE_ALLOW_PRIV parameter to '--allow-privileged=false'"
    52        scored: true
    53  ```
    54  
    55  `controls` is composed of a hierarchy of groups, sub-groups and checks. Each of
    56  the `controls` components have an id and a text description which are displayed 
    57  in the `kube-bench` output.
    58  
    59  `type` specifies what kubernetes node type a `controls` is for. Possible values
    60  for `type` are `master` and `node`.
    61  
    62  ## Groups
    63  
    64  `groups` is a list of subgroups that test the various Kubernetes components
    65  that run on the node type specified in the `controls`. 
    66  
    67  For example, one subgroup checks parameters passed to the API server binary, while 
    68  another subgroup checks parameters passed to the controller-manager binary.
    69  
    70  ```yml
    71  groups:
    72  - id: 1.1
    73    text: API Server
    74    # ...
    75  - id: 1.2
    76    text: Scheduler
    77    # ...
    78  ```
    79  
    80  These subgroups have `id`, `text` fields which serve the same purposes described
    81  in the previous paragraphs. The most important part of the subgroup is the
    82  `checks` field which is the collection of actual `check`s that form the subgroup.
    83  
    84  This is an example of a subgroup and checks in the subgroup.
    85  
    86  ```yml
    87  id: 1.1
    88  text: API Server
    89  checks:
    90    - id: 1.1.1
    91      text: "Ensure that the --allow-privileged argument is set (Scored)"
    92      audit: "ps -ef | grep kube-apiserver | grep -v grep"
    93      tests:
    94      # ...
    95    - id: 1.1.2
    96      text: "Ensure that the --anonymous-auth argument is set to false (Not Scored)"
    97      audit: "ps -ef | grep kube-apiserver | grep -v grep"
    98      tests:
    99      # ...
   100  ``` 
   101  
   102  `kube-bench` supports running a subgroup by specifying the subgroup `id` on the
   103  command line, with the flag `--group` or `-g`.
   104  
   105  ## Check
   106  
   107  The CIS Kubernetes Benchmark recommends configurations to harden Kubernetes components. These recommendations are usually configuration options and can be 
   108  specified by flags to Kubernetes binaries, or in configuration files.
   109  
   110  The Benchmark also provides commands to audit a Kubernetes installation, identify
   111  places where the cluster security can be improved, and steps to remediate these
   112  identified problems.
   113  
   114  In `kube-bench`, `check` objects embody these recommendations.  This an example
   115  `check` object:
   116  
   117  ```yml
   118  id: 1.1.1
   119  text: "Ensure that the --anonymous-auth argument is set to false (Not Scored)"
   120  audit: "ps -ef | grep kube-apiserver | grep -v grep"
   121  tests:
   122    test_items:
   123    - flag: "--anonymous-auth"
   124      compare:
   125        op: eq
   126        value: false
   127      set: true
   128  remediation: |
   129    Edit the API server pod specification file kube-apiserver
   130    on the master node and set the below parameter.
   131    --anonymous-auth=false
   132  scored: false
   133  ```
   134  
   135  A `check` object has an `id`, a `text`, an `audit`, a `tests`, `remediation`
   136  and `scored` fields.
   137  
   138  `kube-bench` supports running individual checks by specifying the check's `id`
   139  as a comma-delimited list on the command line with the `--check` flag.
   140  
   141  The `audit` field specifies the command to run for a check. The output of this
   142  command is then evaluated for conformance with the CIS Kubernetes Benchmark
   143  recommendation.
   144  
   145  The audit is evaluated against criteria specified by the `tests`
   146  object. `tests` contain `bin_op` and `test_items`.
   147  
   148  `test_items` specify the criteria(s) the `audit` command's output should meet to
   149  pass a check. This criteria is made up of keywords extracted from the output of
   150  the `audit` command and operations that compare these keywords against
   151  values expected by the CIS Kubernetes Benchmark. 
   152  
   153  There are three ways to run and extract keywords from the output of the command used, 
   154  | Command | Output var |
   155  |---|---|
   156  | `audit` | `flag` |
   157  | `audit_config` | `path` | 
   158  | `audit_env` | `env` |
   159  
   160  `flag` is used when the keyword is a command-line flag. The associated `audit` command could 
   161  be any binaries available on the system like `ps` command and a `grep` for the binary whose flag we are
   162  checking:
   163  
   164  ```sh
   165  ps -ef | grep somebinary | grep -v grep
   166  ``` 
   167  
   168  Here is an example usage of the `flag` option:
   169  
   170  ```yml
   171  # ...
   172  audit: "ps -ef | grep kube-apiserver | grep -v grep"
   173  tests:
   174    test_items:
   175    - flag: "--anonymous-auth"
   176    # ...
   177  ```
   178  
   179  `path` is used when the keyword is an option set in a JSON or YAML config file.
   180  The associated `audit_command` command is usually `cat /path/to/config-yaml-or-json`.
   181  For example:
   182  
   183  ```yml
   184  # ...
   185  text: "Ensure that the --anonymous-auth argument is set to false (Not Scored)"
   186  audit: "cat /path/to/some/config"
   187  tests:
   188    test_items:
   189    - path: "{.someoption.value}"
   190      # ...
   191  ```
   192  
   193  `env` is used to check if the value is present within a specified environment variable. The presence of `env` is treated as an OR operation, if both `flag` and `env` are supplied it will use either to attempt pass the check.
   194  The command used for checking the environment variables of a process **is generated by default**.
   195  
   196  If the command being generated is causing errors, you can override the command used by setting `audit_env` on the check.
   197  Similarly, if you don't want the environment checking command to be generated or run at all, specify `disableEnvTesting` as true on the check.
   198  
   199  The example below will check if the flag `--auto-tls` is equal to false *OR* `ETCD_AUTO_TLS` is equal to false
   200  
   201  ```yml
   202    test_items:
   203    - flag: "--auto-tls"
   204      env: "ETCD_AUTO_TLS"
   205      compare:
   206        op: eq
   207        value: false
   208  ```
   209  **Note:** flag, path and env will act as OR if more then one present. 
   210  
   211  `test_item` compares the output of the audit command and keywords using the
   212  `set` and `compare` fields.
   213  
   214  ```yml
   215    test_items:
   216    - flag: "--anonymous-auth"
   217      compare:
   218        op: eq
   219        value: false
   220      set: true
   221  ```
   222  
   223  `set` checks if a keyword is present in the output of the audit command or a config file. The possible values for `set` are true and false.
   224  
   225  If `set` is true, the check passes only if the keyword is present in the output
   226  of the audit command, or config file. If `set` is false, the check passes only
   227  if the keyword is not present in the output of the audit command, or config file.
   228  `set` is true by default.
   229  
   230  `compare` has two fields `op` and `value` to compare keywords with expected
   231  value. `op` specifies which operation is used for the comparison, and `value`
   232  specifies the value to compare against.
   233  
   234  > To use `compare`, `set` must true. The comparison will be ignored if `set` is
   235  > false
   236  
   237  The `op` (operations) currently supported in `kube-bench` are:
   238  - `eq`: tests if the keyword is equal to the compared value.
   239  - `noteq`: tests if the keyword is unequal to the compared value.
   240  - `gt`: tests if the keyword is greater than the compared value.
   241  - `gte`: tests if the keyword is greater than or equal to the compared value.
   242  - `lt`: tests if the keyword is less than the compared value.
   243  - `lte`: tests if the keyword is less than or equal to the compared value.
   244  - `has`: tests if the keyword contains the compared value.
   245  - `nothave`: tests if the keyword does not contain the compared value.
   246  - `regex`: tests if the flag value matches the compared value regular expression.
   247     When defining regular expressions in YAML it is generally easier to wrap them in
   248     single quotes, for example `'^[abc]$'`, to avoid issues with string escaping.
   249  - `bitmask` : tests if keyward is bitmasked with the compared value, common usege is for 
   250     comparing file permissions in linux.
   251  
   252  ## Omitting checks
   253  
   254  If you decide that a recommendation is not appropriate for your environment, you can choose to omit it by editing the test YAML file to give it the check type `skip` as in this example:
   255  
   256  ```yaml
   257    checks:
   258    - id: 2.1.1
   259      text: "Ensure that the --allow-privileged argument is set to false (Scored)"
   260      type: "skip"
   261      scored: true
   262  ```
   263  
   264  No tests will be run for this check and the output will be marked [INFO].
   265  
   266  ## Configuration and Variables
   267  
   268  Kubernetes component configuration and binary file locations and names 
   269  vary based on cluster deployment methods and Kubernetes distribution used.
   270  For this reason, the locations of these binaries and config files are configurable
   271  by editing the `cfg/config.yaml` file and these binaries and files can be
   272  referenced in a `controls` file via variables.
   273  
   274  The `cfg/config.yaml` file is a global configuration file. Configuration files
   275  can be created for specific Kubernetes versions (distributions). Values in the
   276  version-specific config overwrite similar values in `cfg/config.yaml`.
   277  
   278  For example, the kube-apiserver in Red Hat OCP distribution is run as 
   279  `hypershift openshift-kube-apiserver` instead of the default `kube-apiserver`.
   280  This difference can be specified by editing the `master.apiserver.defaultbin`
   281  entry `cfg/rh-0.7/config.yaml`.
   282  
   283  Below is the structure of `cfg/config.yaml`:
   284  
   285  ```
   286  nodetype
   287    |-- components
   288      |-- component1
   289    |-- component1
   290      |-- bins
   291      |-- defaultbin (optional)
   292      |-- confs
   293      |-- defaultconf (optional)
   294      |-- svcs
   295      |-- defaultsvc (optional)
   296      |-- kubeconfig
   297      |-- defaultkubeconfig (optional)
   298  ```
   299  
   300  Every node type has a subsection that specifies the main configuration items.
   301  
   302  - `components`: A list of components for the node type. For example master 
   303    will have an entry for **apiserver**, **scheduler** and **controllermanager**.
   304    
   305    Each component has the following entries:
   306  
   307  - `bins`: A list of candidate binaries for a component. `kube-bench` checks this
   308     list and selects the **first** binary that is running on the node.
   309  
   310     If none of the binaries in `bins` list is running, `kube-bench` checks if the
   311     binary specified by `defaultbin` is running and terminates if none of the 
   312     binaries in both `bins` and `defaultbin` is running.
   313     
   314     The selected binary for a component can be referenced in `controls` using a 
   315     variable in the form `$<component>bin`. In the example below, we reference 
   316     the selected API server binary with the variable `$apiserverbin` in an `audit`
   317     command.
   318     
   319     ```yml
   320     id: 1.1.1
   321      text: "Ensure that the --anonymous-auth argument is set to false (Scored)"
   322      audit: "ps -ef | grep $apiserverbin | grep -v grep"
   323      # ...
   324     ```
   325     
   326  - `confs`: A list of candidate configuration files for a component. `kube-bench`
   327    checks this list and selects the **first** config file that is found on the node.
   328    If none of the config files exists, `kube-bench` defaults conf to the value
   329    of `defaultconf`.
   330    
   331    The selected config for a component can be referenced in `controls` using a
   332    variable in the form `$<component>conf`. In the example below, we reference the 
   333    selected API server config file with the variable `$apiserverconf` in an `audit`
   334    command.
   335    
   336    ```yml
   337    id: 1.4.1
   338      text: "Ensure that the API server pod specification file permissions are
   339      set to 644 or more restrictive (Scored)"
   340      audit: "/bin/sh -c 'if test -e $apiserverconf; then stat -c %a $apiserverconf; fi'"
   341    ```
   342    
   343  - `svcs`:  A list of candidate unitfiles for a component. `kube-bench` checks this 
   344    list and selects the **first** unitfile that is found on the node. If none of the
   345    unitfiles exists, `kube-bench` defaults unitfile to the value of `defaultsvc`.
   346    
   347    The selected unitfile for a component can be referenced in `controls` via a
   348    variable in the form `$<component>svc`. In the example below, the selected 
   349    kubelet unitfile is referenced with `$kubeletsvc` in the `remediation` of the 
   350    `check`.
   351    
   352    ```yml
   353    id: 2.1.1
   354      # ...
   355      remediation: |
   356        Edit the kubelet service file $kubeletsvc
   357        on each worker node and set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
   358        --allow-privileged=false
   359        Based on your system, restart the kubelet service. For example:
   360        systemctl daemon-reload
   361        systemctl restart kubelet.service
   362      # ...
   363    ```
   364    
   365    - `kubeconfig`: A list of candidate kubeconfig files for a component. `kube-bench`
   366      checks this list and selects the **first** file that is found on the node. If none
   367      of the files exists, `kube-bench` defaults kubeconfig to the value of 
   368      `defaultkubeconfig`.
   369      
   370      The selected kubeconfig for a component can be referenced in `controls` with a variable in the form `$<component>kubeconfig`. In the example below, the
   371      selected kubelet kubeconfig is referenced with `$kubeletkubeconfig` in the
   372      `audit` command.
   373      
   374      ```yml
   375      id: 2.2.1
   376        text: "Ensure that the kubelet.conf file permissions are set to 644 or
   377        more restrictive (Scored)"
   378        audit: "/bin/sh -c 'if test -e $kubeletkubeconfig; then stat -c %a $kubeletkubeconfig; fi'"
   379        # ...
   380      ```