Skip to content

Commit a3faa62

Browse files
committed
Add TLS support for crictl exec, portforward and attach
Add flags to allow using the TLS based streaming configuration. Signed-off-by: Sascha Grunert <[email protected]>
1 parent c9a62f2 commit a3faa62

File tree

5 files changed

+351
-423
lines changed

5 files changed

+351
-423
lines changed

Diff for: cmd/crictl/attach.go

+29-4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,24 @@ var runtimeAttachCommand = &cli.Command{
5050
Value: transportSpdy,
5151
Usage: fmt.Sprintf("Transport protocol to use, one of: %s|%s", transportSpdy, transportWebsocket),
5252
},
53+
&cli.StringFlag{
54+
Name: flagTLSServerName,
55+
Usage: "Server name used in the TLS client to check server certificates against",
56+
Aliases: []string{"tls-server", "tls-sn"},
57+
Value: "localhost",
58+
},
59+
&cli.StringFlag{
60+
Name: flagTLSCA,
61+
Usage: "Path to the streaming TLS CA certificate",
62+
},
63+
&cli.StringFlag{
64+
Name: flagTLSCert,
65+
Usage: "Path to the streaming TLS certificate",
66+
},
67+
&cli.StringFlag{
68+
Name: flagTLSKey,
69+
Usage: "Path to the streaming TLS key",
70+
},
5371
},
5472
Action: func(c *cli.Context) error {
5573
id := c.Args().First()
@@ -70,10 +88,17 @@ var runtimeAttachCommand = &cli.Command{
7088
defer cancel()
7189

7290
opts := attachOptions{
73-
id: id,
74-
tty: c.Bool("tty"),
75-
stdin: c.Bool("stdin"),
91+
id: id,
92+
tty: c.Bool("tty"),
93+
stdin: c.Bool("stdin"),
94+
transport: c.String("transport"),
95+
}
96+
97+
opts.tlsConfig, err = tlsConfigFromFlags(c)
98+
if err != nil {
99+
return fmt.Errorf("get TLS config from flags: %w", err)
76100
}
101+
77102
if err = Attach(ctx, runtimeClient, opts); err != nil {
78103
return fmt.Errorf("attaching running container failed: %w", err)
79104
}
@@ -116,5 +141,5 @@ func Attach(ctx context.Context, client internalapi.RuntimeService, opts attachO
116141
}
117142

118143
logrus.Debugf("Attach URL: %v", URL)
119-
return stream(ctx, opts.stdin, opts.tty, opts.transport, URL)
144+
return stream(ctx, opts.stdin, opts.tty, opts.transport, URL, opts.tlsConfig)
120145
}

Diff for: cmd/crictl/exec.go

+59-9
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,24 @@ var runtimeExecCommand = &cli.Command{
125125
Aliases: []string{"x"},
126126
Usage: "Run the command in parallel if multiple containers are selected",
127127
},
128+
&cli.StringFlag{
129+
Name: flagTLSServerName,
130+
Usage: "Server name used in the TLS client to check server certificates against",
131+
Aliases: []string{"tls-server", "tls-sn"},
132+
Value: "localhost",
133+
},
134+
&cli.StringFlag{
135+
Name: flagTLSCA,
136+
Usage: "Path to the streaming TLS CA certificate",
137+
},
138+
&cli.StringFlag{
139+
Name: flagTLSCert,
140+
Usage: "Path to the streaming TLS certificate",
141+
},
142+
&cli.StringFlag{
143+
Name: flagTLSKey,
144+
Usage: "Path to the streaming TLS key",
145+
},
128146
},
129147
Action: func(c *cli.Context) error {
130148
if c.NArg() < 1 {
@@ -200,6 +218,11 @@ var runtimeExecCommand = &cli.Command{
200218
transport: c.String(transportFlag),
201219
}
202220

221+
opts.tlsConfig, err = tlsConfigFromFlags(c)
222+
if err != nil {
223+
return fmt.Errorf("get TLS config from flags: %w", err)
224+
}
225+
203226
funcs := []func() error{}
204227
for _, id := range ids {
205228
funcs = append(funcs, func() error {
@@ -210,7 +233,7 @@ var runtimeExecCommand = &cli.Command{
210233
fmt.Println(id + ":")
211234
}
212235
if c.Bool("sync") {
213-
exitCode, err := ExecSync(runtimeClient, optsCopy)
236+
exitCode, err := ExecSync(runtimeClient, &optsCopy)
214237
if err != nil {
215238
return fmt.Errorf("execing command in container %s synchronously: %w", id, err)
216239
}
@@ -220,7 +243,7 @@ var runtimeExecCommand = &cli.Command{
220243
} else {
221244
ctx, cancel := context.WithCancel(c.Context)
222245
defer cancel()
223-
err = Exec(ctx, runtimeClient, optsCopy)
246+
err = Exec(ctx, runtimeClient, &optsCopy)
224247
if err != nil {
225248
return fmt.Errorf("execing command in container %s: %w", id, err)
226249
}
@@ -241,10 +264,37 @@ var runtimeExecCommand = &cli.Command{
241264
},
242265
}
243266

267+
const (
268+
flagTLSServerName = "tls-server-name"
269+
flagTLSCA = "tls-ca"
270+
flagTLSCert = "tls-cert"
271+
flagTLSKey = "tls-key"
272+
)
273+
274+
func tlsConfigFromFlags(ctx *cli.Context) (*rest.TLSClientConfig, error) {
275+
cfg := &rest.TLSClientConfig{
276+
ServerName: ctx.String(flagTLSServerName),
277+
CAFile: ctx.String(flagTLSCA),
278+
CertFile: ctx.String(flagTLSCert),
279+
KeyFile: ctx.String(flagTLSKey),
280+
}
281+
if cfg.CAFile == "" && cfg.CertFile == "" && cfg.KeyFile == "" {
282+
return &rest.TLSClientConfig{Insecure: true}, nil
283+
}
284+
if cfg.CAFile == "" || cfg.CertFile == "" || cfg.KeyFile == "" {
285+
return nil, fmt.Errorf(
286+
"all three flags --%s, --%s and --%s are required for TLS streaming",
287+
flagTLSCA, flagTLSCert, flagTLSKey,
288+
)
289+
}
290+
291+
return cfg, nil
292+
}
293+
244294
// ExecSync sends an ExecSyncRequest to the server, and parses
245295
// the returned ExecSyncResponse. The function returns the corresponding exit
246296
// code beside an general error.
247-
func ExecSync(client internalapi.RuntimeService, opts execOptions) (int, error) {
297+
func ExecSync(client internalapi.RuntimeService, opts *execOptions) (int, error) {
248298
request := &pb.ExecSyncRequest{
249299
ContainerId: opts.id,
250300
Cmd: opts.cmd,
@@ -271,7 +321,7 @@ func ExecSync(client internalapi.RuntimeService, opts execOptions) (int, error)
271321
}
272322

273323
// Exec sends an ExecRequest to server, and parses the returned ExecResponse.
274-
func Exec(ctx context.Context, client internalapi.RuntimeService, opts execOptions) error {
324+
func Exec(ctx context.Context, client internalapi.RuntimeService, opts *execOptions) error {
275325
request := &pb.ExecRequest{
276326
ContainerId: opts.id,
277327
Cmd: opts.cmd,
@@ -305,11 +355,11 @@ func Exec(ctx context.Context, client internalapi.RuntimeService, opts execOptio
305355
}
306356

307357
logrus.Debugf("Exec URL: %v", URL)
308-
return stream(ctx, opts.stdin, opts.tty, opts.transport, URL)
358+
return stream(ctx, opts.stdin, opts.tty, opts.transport, URL, opts.tlsConfig)
309359
}
310360

311-
func stream(ctx context.Context, in, tty bool, transport string, parsedURL *url.URL) error {
312-
executor, err := getExecutor(transport, parsedURL)
361+
func stream(ctx context.Context, in, tty bool, transport string, parsedURL *url.URL, tlsConfig *rest.TLSClientConfig) error {
362+
executor, err := getExecutor(transport, parsedURL, tlsConfig)
313363
if err != nil {
314364
return fmt.Errorf("get executor: %w", err)
315365
}
@@ -348,8 +398,8 @@ func stream(ctx context.Context, in, tty bool, transport string, parsedURL *url.
348398
return t.Safe(func() error { return executor.StreamWithContext(ctx, streamOptions) })
349399
}
350400

351-
func getExecutor(transport string, parsedURL *url.URL) (exec remoteclient.Executor, err error) {
352-
config := &rest.Config{TLSClientConfig: rest.TLSClientConfig{Insecure: true}}
401+
func getExecutor(transport string, parsedURL *url.URL, tlsConfig *rest.TLSClientConfig) (exec remoteclient.Executor, err error) {
402+
config := &rest.Config{TLSClientConfig: *tlsConfig}
353403

354404
switch transport {
355405
case transportSpdy:

Diff for: cmd/crictl/portforward.go

+27-3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,24 @@ var runtimePortForwardCommand = &cli.Command{
4545
Value: transportSpdy,
4646
Usage: fmt.Sprintf("Transport protocol to use, one of: %s|%s", transportSpdy, transportWebsocket),
4747
},
48+
&cli.StringFlag{
49+
Name: flagTLSServerName,
50+
Usage: "Server name used in the TLS client to check server certificates against",
51+
Aliases: []string{"tls-server", "tls-sn"},
52+
Value: "localhost",
53+
},
54+
&cli.StringFlag{
55+
Name: flagTLSCA,
56+
Usage: "Path to the streaming TLS CA certificate",
57+
},
58+
&cli.StringFlag{
59+
Name: flagTLSCert,
60+
Usage: "Path to the streaming TLS certificate",
61+
},
62+
&cli.StringFlag{
63+
Name: flagTLSKey,
64+
Usage: "Path to the streaming TLS key",
65+
},
4866
},
4967
Action: func(c *cli.Context) error {
5068
if c.NArg() < 2 {
@@ -61,6 +79,12 @@ var runtimePortForwardCommand = &cli.Command{
6179
ports: c.Args().Tail(),
6280
transport: c.String(transportFlag),
6381
}
82+
83+
opts.tlsConfig, err = tlsConfigFromFlags(c)
84+
if err != nil {
85+
return fmt.Errorf("get TLS config from flags: %w", err)
86+
}
87+
6488
if err = PortForward(runtimeClient, opts); err != nil {
6589
return fmt.Errorf("port forward: %w", err)
6690
}
@@ -99,7 +123,7 @@ func PortForward(client internalapi.RuntimeService, opts portforwardOptions) err
99123
}
100124

101125
logrus.Debugf("PortForward URL: %v", parsedURL)
102-
dialer, err := getDialer(opts.transport, parsedURL)
126+
dialer, err := getDialer(opts.transport, parsedURL, opts.tlsConfig)
103127
if err != nil {
104128
return fmt.Errorf("get dialer: %w", err)
105129
}
@@ -114,8 +138,8 @@ func PortForward(client internalapi.RuntimeService, opts portforwardOptions) err
114138
return pf.ForwardPorts()
115139
}
116140

117-
func getDialer(transport string, parsedURL *url.URL) (exec httpstream.Dialer, err error) {
118-
config := &rest.Config{TLSClientConfig: rest.TLSClientConfig{Insecure: true}}
141+
func getDialer(transport string, parsedURL *url.URL, tlsConfig *rest.TLSClientConfig) (exec httpstream.Dialer, err error) {
142+
config := &rest.Config{TLSClientConfig: *tlsConfig}
119143

120144
switch transport {
121145
case transportSpdy:

Diff for: cmd/crictl/util.go

+8
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"google.golang.org/protobuf/protoadapt"
3737
"google.golang.org/protobuf/runtime/protoiface"
3838
utilyaml "k8s.io/apimachinery/pkg/util/yaml"
39+
"k8s.io/client-go/rest"
3940
internalapi "k8s.io/cri-api/pkg/apis"
4041
pb "k8s.io/cri-api/pkg/apis/runtime/v1"
4142
"sigs.k8s.io/yaml"
@@ -157,7 +158,10 @@ type execOptions struct {
157158
cmd []string
158159
// transport to be used
159160
transport string
161+
// TLS configuration for streaming
162+
tlsConfig *rest.TLSClientConfig
160163
}
164+
161165
type attachOptions struct {
162166
// id of container
163167
id string
@@ -167,6 +171,8 @@ type attachOptions struct {
167171
stdin bool
168172
// transport to be used
169173
transport string
174+
// TLS configuration for streaming
175+
tlsConfig *rest.TLSClientConfig
170176
}
171177

172178
type portforwardOptions struct {
@@ -176,6 +182,8 @@ type portforwardOptions struct {
176182
ports []string
177183
// transport to be used
178184
transport string
185+
// TLS configuration for streaming
186+
tlsConfig *rest.TLSClientConfig
179187
}
180188

181189
func getSortedKeys(m map[string]string) []string {

0 commit comments

Comments
 (0)