Skip to content

Commit 39ed562

Browse files
committed
Use server side dry run on admission control scan
Added a flag --admission-create to replicate the old behavior but the scan now by default run with --dry-run=server so no cleaning is needed. Shoutout to @smarticu5 for the idea at KubeHuddle 2022!
1 parent 9b47448 commit 39ed562

File tree

4 files changed

+103
-84
lines changed

4 files changed

+103
-84
lines changed

README.md

Lines changed: 68 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ Aliases:
167167
dig, d
168168

169169
Flags:
170+
--admission-create Actually create pods to scan admission instead of using server dry run. (this flag is specific to the admission bucket)
170171
--admission-force Force creation of pods to scan admission even without cleaning rights. (this flag is specific to the admission bucket)
171172
-c, --color Enable color in output. (default true if output is human)
172173
-h, --help help for dig
@@ -244,6 +245,9 @@ instance, if the `hostname` syscall is successful, it will replace the
244245
hostname with the empty string. So please, **NEVER** run with
245246
sufficient permissions (as root for example) directly on your machine.
246247

248+
The admission scan will by default run as server dry-run but will generate API
249+
server logs.
250+
247251
### Results warning
248252

249253
Some tests are based on details of implementation or side effects on the
@@ -345,69 +349,71 @@ You can list and describe the available buckets (or plugins) with `kdigger
345349
list` or `kdigger ls`:
346350
```console
347351
$ kdigger ls
348-
+---------------+----------------------------+--------------------------------------+-------------+---------------+
349-
| NAME | ALIASES | DESCRIPTION | SIDEEFFECTS | REQUIRECLIENT |
350-
+---------------+----------------------------+--------------------------------------+-------------+---------------+
351-
| admission | [admissions adm] | Admission scans the admission | true | true |
352-
| | | controller chain by creating | | |
353-
| | | specific pods to find what is | | |
354-
| | | prevented or not. | | |
355-
| apiresources | [api apiresource] | APIResources discovers the available | false | true |
356-
| | | APIs of the cluster. | | |
357-
| authorization | [authorizations auth] | Authorization checks your API | false | true |
358-
| | | permissions with the current context | | |
359-
| | | or the available token. | | |
360-
| capabilities | [capability cap] | Capabilities lists all capabilities | false | false |
361-
| | | in all sets and displays dangerous | | |
362-
| | | capabilities in red. | | |
363-
| cgroups | [cgroup cg] | Cgroups reads the /proc/self/cgroup | false | false |
364-
| | | files that can leak information | | |
365-
| | | under cgroups v1. | | |
366-
| cloudmetadata | [cloud meta] | Cloudmetadata scans the usual | false | false |
367-
| | | metadata endpoints in public clouds. | | |
368-
| devices | [device dev] | Devices shows the list of devices | false | false |
369-
| | | available in the container. | | |
370-
| environment | [environments environ env] | Environment checks the presence of | false | false |
371-
| | | kubernetes related environment | | |
372-
| | | variables and shows them. | | |
373-
| mount | [mounts mn] | Mount shows all mounted devices in | false | false |
374-
| | | the container. | | |
375-
| node | [nodes n] | Node retrieves various information | false | false |
376-
| | | in /proc about the current host. | | |
377-
| pidnamespace | [pidnamespaces pidns] | PIDnamespace analyses the PID | false | false |
378-
| | | namespace of the container in the | | |
379-
| | | context of Kubernetes. | | |
380-
| processes | [process ps] | Processes analyses the running | false | false |
381-
| | | processes in your PID namespace | | |
382-
| runtime | [runtimes rt] | Runtime finds clues to identify | false | false |
383-
| | | which container runtime is running | | |
384-
| | | the container. | | |
385-
| services | [service svc] | Services uses CoreDNS wildcards | false | false |
386-
| | | feature to discover every service | | |
387-
| | | available in the cluster. | | |
388-
| syscalls | [syscall sys] | Syscalls scans most of the syscalls | true | false |
389-
| | | to detect which are blocked and | | |
390-
| | | allowed. | | |
391-
| token | [tokens tk] | Token checks for the presence of a | false | false |
392-
| | | service account token in the | | |
393-
| | | filesystem. | | |
394-
| userid | [userids id] | UserID retrieves UID, GID and their | false | false |
395-
| | | corresponding names. | | |
396-
| usernamespace | [usernamespaces userns] | UserNamespace analyses the user | false | false |
397-
| | | namespace configuration. | | |
398-
| version | [versions v] | Version dumps the API server version | false | true |
399-
| | | informations. | | |
400-
+---------------+----------------------------+--------------------------------------+-------------+---------------+
352+
+-----------------+----------------------------+----------------------------------------+-------------+---------------+
353+
| NAME | ALIASES | DESCRIPTION | SIDEEFFECTS | REQUIRECLIENT |
354+
+-----------------+----------------------------+----------------------------------------+-------------+---------------+
355+
| admission | [admissions adm] | Admission scans the admission | true | true |
356+
| | | controller chain by creating (by | | |
357+
| | | default with dry run) specific pods to | | |
358+
| | | find what is prevented or not. | | |
359+
| apiresources | [api apiresource] | APIResources discovers the available | false | true |
360+
| | | APIs of the cluster. | | |
361+
| authorization | [authorizations auth] | Authorization checks your API | false | true |
362+
| | | permissions with the current context | | |
363+
| | | or the available token. | | |
364+
| capabilities | [capability cap] | Capabilities lists all capabilities in | false | false |
365+
| | | all sets and displays dangerous | | |
366+
| | | capabilities in red. | | |
367+
| cgroups | [cgroup cg] | Cgroups reads the /proc/self/cgroup | false | false |
368+
| | | files that can leak information under | | |
369+
| | | cgroups v1. | | |
370+
| cloudmetadata | [cloud meta] | Cloudmetadata scans the usual metadata | false | false |
371+
| | | endpoints in public clouds. | | |
372+
| containerdetect | [container cdetect] | ContainerDetect retrieves hints that | false | false |
373+
| | | the process is running inside a | | |
374+
| | | typical container. | | |
375+
| devices | [device dev] | Devices shows the list of devices | false | false |
376+
| | | available in the container. | | |
377+
| environment | [environments environ env] | Environment checks the presence of | false | false |
378+
| | | kubernetes related environment | | |
379+
| | | variables and shows them. | | |
380+
| mount | [mounts mn] | Mount shows all mounted devices in the | false | false |
381+
| | | container. | | |
382+
| node | [nodes n] | Node retrieves various information in | false | false |
383+
| | | /proc about the current host. | | |
384+
| pidnamespace | [pidnamespaces pidns] | PIDnamespace analyses the PID | false | false |
385+
| | | namespace of the container in the | | |
386+
| | | context of Kubernetes. | | |
387+
| processes | [process ps] | Processes analyses the running | false | false |
388+
| | | processes in your PID namespace | | |
389+
| runtime | [runtimes rt] | Runtime finds clues to identify which | false | false |
390+
| | | container runtime is running the | | |
391+
| | | container. | | |
392+
| services | [service svc] | Services uses CoreDNS wildcards | false | false |
393+
| | | feature to discover every service | | |
394+
| | | available in the cluster. | | |
395+
| syscalls | [syscall sys] | Syscalls scans most of the syscalls to | true | false |
396+
| | | detect which are blocked and allowed. | | |
397+
| token | [tokens tk] | Token checks for the presence of a | false | false |
398+
| | | service account token in the | | |
399+
| | | filesystem. | | |
400+
| userid | [userids id] | UserID retrieves UID, GID and their | false | false |
401+
| | | corresponding names. | | |
402+
| usernamespace | [usernamespaces userns] | UserNamespace analyses the user | false | false |
403+
| | | namespace configuration. | | |
404+
| version | [versions v] | Version dumps the API server version | false | true |
405+
| | | informations. | | |
406+
+-----------------+----------------------------+----------------------------------------+-------------+---------------+
401407
```
402408

403409
### Admission
404410

405-
Admission scans the admission controller chain by creating specific pods to
406-
find what is prevented or not. The idea behind this bucket is to check, after
407-
you learned that you have `create pods` ability, if no admission controller
408-
like a PodSecurityPolicy or another is blocking you to create node privilege
409-
escalation pods. Like mounting the host filesystem, or the host PID namespace,
410-
or just a privileged container, for example.
411+
Admission scans the admission controller chain by creating (by default with dry
412+
run) specific pods to find what is prevented or not. The idea behind this bucket
413+
is to check, after you learned that you have `create pods` ability, if no
414+
admission controller like a PodSecurityPolicy or another is blocking you to
415+
create node privilege escalation pods. Like mounting the host filesystem, or the
416+
host PID namespace, or just a privileged container, for example.
411417

412418
This bucket currently automatically tries to create:
413419
- a privileged pod
@@ -420,6 +426,9 @@ This bucket currently automatically tries to create:
420426
So, if you are granted rights to `create pods`, you can check the presence of
421427
any admission controller that might restrict you.
422428

429+
Note that it uses `--dry-run=server` by default but you can really create the
430+
pods with the `--admission-create` admission plugin specific flag.
431+
423432
### API Resources
424433

425434
APIResources discovers the available APIs of the cluster. These endpoints are

commands/dig.go

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,16 @@ var kubeconfig string
1919
// flag for the namespace
2020
var namespace string
2121

22-
// flag for the color
23-
var color bool
24-
2522
// flag to activate side effects buckets
2623
var sideEffects bool
2724

28-
// flag to force admission creation
29-
var admForce bool
30-
3125
// output formats
3226
const outputHuman = "human"
3327
const outputJSON = "json"
3428

29+
// config that will carry parameters and client for plugin init
30+
var pluginConfig bucket.Config
31+
3532
// digCmd represents the dig command
3633
var digCmd = &cobra.Command{
3734
Use: "dig [buckets]",
@@ -53,7 +50,7 @@ arguments.`,
5350

5451
// apply default colored human only if the color flag was not set
5552
if !cmd.Flags().Changed("color") && output == outputHuman {
56-
color = true
53+
pluginConfig.Color = true
5754
}
5855

5956
// check if any called buckets have side effects without the flag activated
@@ -74,13 +71,6 @@ arguments.`,
7471
return nil
7572
},
7673
RunE: func(cmd *cobra.Command, args []string) error {
77-
// create the config that will be passed to every plugins
78-
config := &bucket.Config{
79-
Color: color,
80-
OutputWidth: outputWidth,
81-
AdmForce: admForce,
82-
}
83-
8474
// handles the "all" or "a" and erase the args with the bucket list
8575
// PreRun should guarantee that len(args) != 0 but in case
8676
if len(args) != 0 {
@@ -107,7 +97,7 @@ arguments.`,
10797
for _, name := range args {
10898
// initialize the bucket
10999
if buckets.RequiresClient(name) {
110-
err := loadContext(config)
100+
err := loadContext(&pluginConfig)
111101
if err != nil {
112102
// loading the context failed and is required so skip this
113103
// execution after printing the error with the name
@@ -118,7 +108,7 @@ arguments.`,
118108
continue
119109
}
120110
}
121-
b, err := buckets.InitBucket(name, *config)
111+
b, err := buckets.InitBucket(name, pluginConfig)
122112
if err != nil {
123113
return err
124114
}
@@ -191,7 +181,11 @@ func init() {
191181
}
192182

193183
digCmd.Flags().StringVarP(&namespace, "namespace", "n", "", "Kubernetes namespace to use. (default to the namespace in the context)")
194-
digCmd.Flags().BoolVarP(&color, "color", "c", false, "Enable color in output. (default true if output is human)")
195184
digCmd.Flags().BoolVarP(&sideEffects, "side-effects", "s", false, "Enable all buckets that might have side effect on environment.")
196-
digCmd.Flags().BoolVarP(&admForce, "admission-force", "", false, "Force creation of pods to scan admission even without cleaning rights. (this flag is specific to the admission bucket)")
185+
186+
digCmd.Flags().BoolVarP(&pluginConfig.Color, "color", "c", false, "Enable color in output. (default true if output is human)")
187+
digCmd.Flags().BoolVarP(&pluginConfig.AdmForce, "admission-force", "", false, "Force creation of pods to scan admission even without cleaning rights. (this flag is specific to the admission bucket)")
188+
digCmd.Flags().BoolVarP(&pluginConfig.AdmCreate, "admission-create", "", false, "Actually create pods to scan admission instead of using server dry run. (this flag is specific to the admission bucket)")
189+
// this one is retrieved from the root cmd because applicable to many cmds
190+
pluginConfig.OutputWidth = outputWidth
197191
}

pkg/bucket/bucket.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ type Config struct {
5555
// This options is specific to the admission plugin, is it to force creation
5656
// even if we can't cleanup the mess with delete
5757
AdmForce bool
58+
// This options is specific to the admission plugin, is it to actually create
59+
// pod instead of use the dry run
60+
AdmCreate bool
5861
}
5962

6063
func NewBuckets() *Buckets {

0 commit comments

Comments
 (0)