Skip to content

Commit

Permalink
Use server side dry run on admission control scan
Browse files Browse the repository at this point in the history
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!
  • Loading branch information
mtardy committed Oct 13, 2022
1 parent 9b47448 commit 39ed562
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 84 deletions.
127 changes: 68 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ Aliases:
dig, d

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

The admission scan will by default run as server dry-run but will generate API
server logs.

### Results warning

Some tests are based on details of implementation or side effects on the
Expand Down Expand Up @@ -345,69 +349,71 @@ You can list and describe the available buckets (or plugins) with `kdigger
list` or `kdigger ls`:
```console
$ kdigger ls
+---------------+----------------------------+--------------------------------------+-------------+---------------+
| NAME | ALIASES | DESCRIPTION | SIDEEFFECTS | REQUIRECLIENT |
+---------------+----------------------------+--------------------------------------+-------------+---------------+
| admission | [admissions adm] | Admission scans the admission | true | true |
| | | controller chain by creating | | |
| | | specific pods to find what is | | |
| | | prevented or not. | | |
| apiresources | [api apiresource] | APIResources discovers the available | false | true |
| | | APIs of the cluster. | | |
| authorization | [authorizations auth] | Authorization checks your API | false | true |
| | | permissions with the current context | | |
| | | or the available token. | | |
| capabilities | [capability cap] | Capabilities lists all capabilities | false | false |
| | | in all sets and displays dangerous | | |
| | | capabilities in red. | | |
| cgroups | [cgroup cg] | Cgroups reads the /proc/self/cgroup | false | false |
| | | files that can leak information | | |
| | | under cgroups v1. | | |
| cloudmetadata | [cloud meta] | Cloudmetadata scans the usual | false | false |
| | | metadata endpoints in public clouds. | | |
| devices | [device dev] | Devices shows the list of devices | false | false |
| | | available in the container. | | |
| environment | [environments environ env] | Environment checks the presence of | false | false |
| | | kubernetes related environment | | |
| | | variables and shows them. | | |
| mount | [mounts mn] | Mount shows all mounted devices in | false | false |
| | | the container. | | |
| node | [nodes n] | Node retrieves various information | false | false |
| | | in /proc about the current host. | | |
| pidnamespace | [pidnamespaces pidns] | PIDnamespace analyses the PID | false | false |
| | | namespace of the container in the | | |
| | | context of Kubernetes. | | |
| processes | [process ps] | Processes analyses the running | false | false |
| | | processes in your PID namespace | | |
| runtime | [runtimes rt] | Runtime finds clues to identify | false | false |
| | | which container runtime is running | | |
| | | the container. | | |
| services | [service svc] | Services uses CoreDNS wildcards | false | false |
| | | feature to discover every service | | |
| | | available in the cluster. | | |
| syscalls | [syscall sys] | Syscalls scans most of the syscalls | true | false |
| | | to detect which are blocked and | | |
| | | allowed. | | |
| token | [tokens tk] | Token checks for the presence of a | false | false |
| | | service account token in the | | |
| | | filesystem. | | |
| userid | [userids id] | UserID retrieves UID, GID and their | false | false |
| | | corresponding names. | | |
| usernamespace | [usernamespaces userns] | UserNamespace analyses the user | false | false |
| | | namespace configuration. | | |
| version | [versions v] | Version dumps the API server version | false | true |
| | | informations. | | |
+---------------+----------------------------+--------------------------------------+-------------+---------------+
+-----------------+----------------------------+----------------------------------------+-------------+---------------+
| NAME | ALIASES | DESCRIPTION | SIDEEFFECTS | REQUIRECLIENT |
+-----------------+----------------------------+----------------------------------------+-------------+---------------+
| admission | [admissions adm] | Admission scans the admission | true | true |
| | | controller chain by creating (by | | |
| | | default with dry run) specific pods to | | |
| | | find what is prevented or not. | | |
| apiresources | [api apiresource] | APIResources discovers the available | false | true |
| | | APIs of the cluster. | | |
| authorization | [authorizations auth] | Authorization checks your API | false | true |
| | | permissions with the current context | | |
| | | or the available token. | | |
| capabilities | [capability cap] | Capabilities lists all capabilities in | false | false |
| | | all sets and displays dangerous | | |
| | | capabilities in red. | | |
| cgroups | [cgroup cg] | Cgroups reads the /proc/self/cgroup | false | false |
| | | files that can leak information under | | |
| | | cgroups v1. | | |
| cloudmetadata | [cloud meta] | Cloudmetadata scans the usual metadata | false | false |
| | | endpoints in public clouds. | | |
| containerdetect | [container cdetect] | ContainerDetect retrieves hints that | false | false |
| | | the process is running inside a | | |
| | | typical container. | | |
| devices | [device dev] | Devices shows the list of devices | false | false |
| | | available in the container. | | |
| environment | [environments environ env] | Environment checks the presence of | false | false |
| | | kubernetes related environment | | |
| | | variables and shows them. | | |
| mount | [mounts mn] | Mount shows all mounted devices in the | false | false |
| | | container. | | |
| node | [nodes n] | Node retrieves various information in | false | false |
| | | /proc about the current host. | | |
| pidnamespace | [pidnamespaces pidns] | PIDnamespace analyses the PID | false | false |
| | | namespace of the container in the | | |
| | | context of Kubernetes. | | |
| processes | [process ps] | Processes analyses the running | false | false |
| | | processes in your PID namespace | | |
| runtime | [runtimes rt] | Runtime finds clues to identify which | false | false |
| | | container runtime is running the | | |
| | | container. | | |
| services | [service svc] | Services uses CoreDNS wildcards | false | false |
| | | feature to discover every service | | |
| | | available in the cluster. | | |
| syscalls | [syscall sys] | Syscalls scans most of the syscalls to | true | false |
| | | detect which are blocked and allowed. | | |
| token | [tokens tk] | Token checks for the presence of a | false | false |
| | | service account token in the | | |
| | | filesystem. | | |
| userid | [userids id] | UserID retrieves UID, GID and their | false | false |
| | | corresponding names. | | |
| usernamespace | [usernamespaces userns] | UserNamespace analyses the user | false | false |
| | | namespace configuration. | | |
| version | [versions v] | Version dumps the API server version | false | true |
| | | informations. | | |
+-----------------+----------------------------+----------------------------------------+-------------+---------------+
```

### Admission

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

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

Note that it uses `--dry-run=server` by default but you can really create the
pods with the `--admission-create` admission plugin specific flag.

### API Resources

APIResources discovers the available APIs of the cluster. These endpoints are
Expand Down
30 changes: 12 additions & 18 deletions commands/dig.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,16 @@ var kubeconfig string
// flag for the namespace
var namespace string

// flag for the color
var color bool

// flag to activate side effects buckets
var sideEffects bool

// flag to force admission creation
var admForce bool

// output formats
const outputHuman = "human"
const outputJSON = "json"

// config that will carry parameters and client for plugin init
var pluginConfig bucket.Config

// digCmd represents the dig command
var digCmd = &cobra.Command{
Use: "dig [buckets]",
Expand All @@ -53,7 +50,7 @@ arguments.`,

// apply default colored human only if the color flag was not set
if !cmd.Flags().Changed("color") && output == outputHuman {
color = true
pluginConfig.Color = true
}

// check if any called buckets have side effects without the flag activated
Expand All @@ -74,13 +71,6 @@ arguments.`,
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
// create the config that will be passed to every plugins
config := &bucket.Config{
Color: color,
OutputWidth: outputWidth,
AdmForce: admForce,
}

// handles the "all" or "a" and erase the args with the bucket list
// PreRun should guarantee that len(args) != 0 but in case
if len(args) != 0 {
Expand All @@ -107,7 +97,7 @@ arguments.`,
for _, name := range args {
// initialize the bucket
if buckets.RequiresClient(name) {
err := loadContext(config)
err := loadContext(&pluginConfig)
if err != nil {
// loading the context failed and is required so skip this
// execution after printing the error with the name
Expand All @@ -118,7 +108,7 @@ arguments.`,
continue
}
}
b, err := buckets.InitBucket(name, *config)
b, err := buckets.InitBucket(name, pluginConfig)
if err != nil {
return err
}
Expand Down Expand Up @@ -191,7 +181,11 @@ func init() {
}

digCmd.Flags().StringVarP(&namespace, "namespace", "n", "", "Kubernetes namespace to use. (default to the namespace in the context)")
digCmd.Flags().BoolVarP(&color, "color", "c", false, "Enable color in output. (default true if output is human)")
digCmd.Flags().BoolVarP(&sideEffects, "side-effects", "s", false, "Enable all buckets that might have side effect on environment.")
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)")

digCmd.Flags().BoolVarP(&pluginConfig.Color, "color", "c", false, "Enable color in output. (default true if output is human)")
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)")
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)")
// this one is retrieved from the root cmd because applicable to many cmds
pluginConfig.OutputWidth = outputWidth
}
3 changes: 3 additions & 0 deletions pkg/bucket/bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ type Config struct {
// This options is specific to the admission plugin, is it to force creation
// even if we can't cleanup the mess with delete
AdmForce bool
// This options is specific to the admission plugin, is it to actually create
// pod instead of use the dry run
AdmCreate bool
}

func NewBuckets() *Buckets {
Expand Down
Loading

0 comments on commit 39ed562

Please sign in to comment.