Skip to content

Commit 914f3d3

Browse files
authored
Misc enhancements (#103)
* - Add support for pulling debug image from IBM Cloud Repository. In IBM Cloud the secrets are stored in a JSON blob instead of the key value pair authStr:<secret>. So if we don't find an 'authStr' value we look for the JSON blob. - Add additional logging around registry authentication + fix grammar in a log message. - For boolean switches ( e.g. port-forward ) that had a default value of true it wasn't possible to specify a value of false in the config file. Because of a logic bug kubectl-debug would ignore the value from the config file in this case. - kubectl-debug couldn't find the config file on Windows because it was using the wrong path separator. * Make it ossible to 'lock' the debugger image by setting env var KCTLDBG_RESTRICT_IMAGE_TO to the uri of the image you want to have used. * Merge auditing feature. * Fix spelling.
1 parent 98903d2 commit 914f3d3

File tree

8 files changed

+330
-47
lines changed

8 files changed

+330
-47
lines changed

README.md

+63
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,69 @@ PS: `kubectl-debug` will always override the entrypoint of the container, which
213213

214214
Currently, `kubectl-debug` reuse the privilege of the `pod/exec` sub resource to do authorization, which means that it has the same privilege requirements with the `kubectl exec` command.
215215

216+
# Auditing / Security
217+
218+
Some teams may want to limit what debug image users are allowed to use and to have an audit record for each command they run in the debug container.
219+
220+
You can use the environment variable ```KCTLDBG_RESTRICT_IMAGE_TO``` restrict the agent to using a specific container image. For example putting the following in the container spec section of your daemonset yaml will force the agent to always use the image ```docker.io/nicolaka/netshoot:latest``` regardless of what the user specifies on the kubectl-debug command line
221+
```
222+
env :
223+
- name: KCTLDBG_RESTRICT_IMAGE_TO
224+
value: docker.io/nicolaka/netshoot:latest
225+
```
226+
If ```KCTLDBG_RESTRICT_IMAGE_TO``` is set and as a result agent is using an image that is different than what the user requested then the agent will log to standard out a message that announces what is happening. The message will include the URI's of both images.
227+
228+
Auditing can be enabled by placing
229+
```audit: true```
230+
in the agent's config file.
231+
232+
There are 3 settings related to auditing.
233+
<dl>
234+
<dt><code>audit</code></dt>
235+
<dd>Boolean value that indicates whether auditing should be enabled or not. Default value is <code>false</code></dd>
236+
<dt><code>audit_fifo</code></dt>
237+
<dd>Template of path to a FIFO that will be used to exchange audit information from the debug container to the agent. The default value is <code>/var/data/kubectl-debug-audit-fifo/KCTLDBG-CONTAINER-ID</code>. If auditing is enabled then the agent will :
238+
<ol>
239+
<li>Prior to creating the debug container, create a fifo based on the value of <code>audit_fifo</code>. The agent will replace <code>KCTLDBG-CONTAINER-ID</code> with the id of the debug container it is creating.</li>
240+
<li>Create a thread that reads lines of text from the FIFO and then writes log messages to standard out, where the log messages look similar to example below <br/>
241+
<code>
242+
2020/05/22 17:59:58 runtime.go:717: audit - user: USERNAME/885cbd0506868985a6fc491bb59a2d3c debugee: 48107cbdacf4b478cbf1e2e34dbea6ebb48a2942c5f3d1effbacf0a216eac94f exec: 265 execve("/bin/tar", ["tar", "--help"], 0x55a8d0dfa6c0 /* 7 vars */) = 0
243+
</code><br/>
244+
Where USERNAME is the kubernetes user as determined by the client that launched the debug container and debuggee is the container id of the container being debugged.
245+
</li>
246+
<li>Bind mount the fifo it creates to the debugger container. </li>
247+
</ol>
248+
</dd>
249+
<dt><code>audit_shim</code>
250+
<dd>String array that will be placed before the command that will be run in the debug container. The default value is <code>{"/usr/bin/strace", "-o", "KCTLDBG-FIFO", "-f", "-e", "trace=/exec"}</code>. The agent will replace KCTLDBG-FIFO with the fifo path ( see above ) If auditing is enabled then agent will use the concatenation of the array specified by <code>audit_shim</code> and the original command array it was going to use.</dd>
251+
</dl>
252+
253+
The easiest way to enable auditing is to define a config map in the yaml you use to deploy the deamonset. You can do this by place
254+
```
255+
apiVersion : v1
256+
kind: ConfigMap
257+
metadata:
258+
name : kubectl-debug-agent-config
259+
data:
260+
agent-config.yml: |
261+
audit: true
262+
---
263+
```
264+
at the top of the file, adding a ```configmap``` volume like so
265+
```
266+
- name: config
267+
configMap:
268+
name: kubectl-debug-agent-config
269+
```
270+
and a volume mount like so
271+
```
272+
- name: config
273+
mountPath: "/etc/kubectl-debug/agent-config.yml"
274+
subPath: agent-config.yml
275+
```
276+
.
277+
278+
216279
# Roadmap
217280
218281
`kubectl-debug` is supposed to be just a troubleshooting helper, and is going be replaced by the native `kubectl debug` command when [this proposal](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/troubleshoot-running-pods.md) is implemented and merged in the future kubernetes release. But for now, there is still some works to do to improve `kubectl-debug`.

go.sum

+3
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,8 @@ k8s.io/apiserver v0.0.0-20181220070914-ce7b605bead3 h1:GIl6hq5bRA5OSLauW8qCPfibG
368368
k8s.io/apiserver v0.0.0-20181220070914-ce7b605bead3/go.mod h1:6bqaTSOSJavUIXUtfaR9Os9JtTCm8ZqH2SUl2S60C4w=
369369
k8s.io/cli-runtime v0.0.0-20190228180923-a9e421a79326 h1:uMY/EHQt0VHYgRMPWwPl/vQ0K0fPlt5zxTEGAdt8pDg=
370370
k8s.io/cli-runtime v0.0.0-20190228180923-a9e421a79326/go.mod h1:qWnH3/b8sp/l7EvlDh7ulDU3UWA4P4N1NFbEEP791tM=
371+
k8s.io/cli-runtime v0.18.2 h1:JiTN5RgkFNTiMxHBRyrl6n26yKWAuNRlei1ZJALUmC8=
372+
k8s.io/cli-runtime v0.18.3 h1:8IBtaTYmXiXipKdx2FAKotvnQMjcF0kSLvX4szY340c=
371373
k8s.io/client-go v0.0.0-20190228174230-b40b2a5939e4 h1:aE8wOCKuoRs2aU0OP/Rz8SXiAB0FTTku3VtGhhrkSmc=
372374
k8s.io/client-go v0.0.0-20190228174230-b40b2a5939e4/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
373375
k8s.io/client-go v1.5.1 h1:XaX/lo2/u3/pmFau8HN+sB5C/b4dc4Dmm2eXjBH4p1E=
@@ -379,6 +381,7 @@ k8s.io/kube-openapi v0.0.0-20190320154901-5e45bb682580/go.mod h1:BXM9ceUBTj2QnfH
379381
k8s.io/kubernetes v1.13.1 h1:IwCCcPOZwY9rKcQyBJYXAE4Wgma4oOW5NYR3HXKFfZ8=
380382
k8s.io/kubernetes v1.13.1/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
381383
k8s.io/kubernetes v1.18.1 h1:qW6zgSY96X/NO+ueIIfsFSbHl/e0Txio62XcA4cxpIk=
384+
k8s.io/kubernetes v1.18.2 h1:37sJPq6p+gx5hEHQSwCWXIiXDc9AajzV1A5UrswnDq0=
382385
k8s.io/utils v0.0.0-20181115163542-0d26856f57b3 h1:S3/Kq185JnolOEemhmDXXd23l2t4bX5hPQPQPADlF1E=
383386
k8s.io/utils v0.0.0-20181115163542-0d26856f57b3/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
384387
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=

pkg/agent/config.go

+11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package agent
22

33
import (
4+
"fmt"
45
"io/ioutil"
56
"time"
67

@@ -16,6 +17,9 @@ var (
1617
StreamCreationTimeout: 15 * time.Second,
1718

1819
ListenAddress: "0.0.0.0:10027",
20+
21+
AuditFifo: "/var/data/kubectl-debug-audit-fifo/KCTLDBG-CONTAINER-ID",
22+
AuditShim: []string{"/usr/bin/strace", "-o", "KCTLDBG-FIFO", "-f", "-e", "trace=/exec"},
1923
}
2024
)
2125

@@ -28,6 +32,10 @@ type Config struct {
2832

2933
ListenAddress string `yaml:"listen_address,omitempty"`
3034
Verbosity int `yaml:"verbosity,omitempty"`
35+
36+
Audit bool `yaml:"audit,omitempty"`
37+
AuditFifo string `yaml:"audit_fifo,omitempty"`
38+
AuditShim []string `yaml:"audit_shim,omitempty"`
3139
}
3240

3341
func Load(s string) (*Config, error) {
@@ -38,6 +46,7 @@ func Load(s string) (*Config, error) {
3846
*cfg = DefaultConfig
3947

4048
err := yaml.UnmarshalStrict([]byte(s), cfg)
49+
fmt.Printf("Config after reading from file %v\r\n", cfg)
4150
if err != nil {
4251
return nil, err
4352
}
@@ -46,8 +55,10 @@ func Load(s string) (*Config, error) {
4655

4756
func LoadFile(filename string) (*Config, error) {
4857
if len(filename) < 1 {
58+
fmt.Println("No config file provided. Using all default values.")
4959
return &DefaultConfig, nil
5060
}
61+
fmt.Printf("Reading config file %v.\r\n", filename)
5162
c, err := ioutil.ReadFile(filename)
5263
if err != nil {
5364
return nil, err

0 commit comments

Comments
 (0)