Skip to content

Commit 4077bb3

Browse files
GoodOwljsternberg
authored andcommitted
buildctl: fix tlsdir handling logic for cert-manager.io
`tldir` flag handling now properly handles the old logic and the new logic for cert-manager.io without failing. Improved error message when files are missing. Co-authored-by: Gleb Nebolyubov <[email protected]> Signed-off-by: Jonathan A. Sternberg <[email protected]>
1 parent 9def9e5 commit 4077bb3

4 files changed

Lines changed: 114 additions & 27 deletions

File tree

cmd/buildctl/common/common.go

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,38 +30,25 @@ func ResolveClient(c *cli.Context) (*client.Client, error) {
3030
serverName = uri.Hostname()
3131
}
3232

33-
var caCert string
34-
var cert string
35-
var key string
33+
var (
34+
caCert string
35+
cert string
36+
key string
37+
err error
38+
)
3639

3740
tlsDir := c.GlobalString("tlsdir")
3841

3942
if tlsDir != "" {
40-
// Look for ca.pem or ca.crt and, if it exists, set caCert to that
41-
// Look for cert.pem or tls.crt and, if it exists, set cert to that
42-
// Look for key.pem or tls.key and, if it exists, set key to that
43-
for _, v := range [6]string{"ca.pem", "cert.pem", "key.pem", "ca.crt", "tls.crt", "tls.key"} {
44-
file := filepath.Join(tlsDir, v)
45-
if _, err := os.Stat(file); err == nil {
46-
switch v {
47-
case "ca.pem":
48-
case "ca.crt":
49-
caCert = file
50-
case "cert.pem":
51-
case "tls.crt":
52-
cert = file
53-
case "key.pem":
54-
case "tls.key":
55-
key = file
56-
}
57-
} else {
58-
return nil, err
59-
}
60-
}
61-
43+
// Fail straight away if TLS was specified both ways
6244
if c.GlobalString("tlscacert") != "" || c.GlobalString("tlscert") != "" || c.GlobalString("tlskey") != "" {
6345
return nil, errors.New("cannot specify tlsdir and tlscacert/tlscert/tlskey at the same time")
6446
}
47+
48+
caCert, cert, key, err = resolveTLSFilesFromDir(tlsDir)
49+
if err != nil {
50+
return nil, err
51+
}
6552
} else {
6653
caCert = c.GlobalString("tlscacert")
6754
cert = c.GlobalString("tlscert")
@@ -128,3 +115,29 @@ func ParseTemplate(format string) (*template.Template, error) {
128115
}
129116
return template.New("").Funcs(funcs).Parse(format)
130117
}
118+
119+
// resolveTLSFilesFromDir scans a TLS directory for known cert/key filenames.
120+
func resolveTLSFilesFromDir(tlsDir string) (caCert, cert, key string, err error) {
121+
oneOf := func(either, or string) (string, error) {
122+
for _, name := range []string{either, or} {
123+
fpath := filepath.Join(tlsDir, name)
124+
if _, err := os.Stat(fpath); err == nil {
125+
return fpath, nil
126+
} else if !os.IsNotExist(err) {
127+
return "", err
128+
}
129+
}
130+
return "", errors.Errorf("directory did not contain one of the needed files: %s or %s", either, or)
131+
}
132+
133+
if caCert, err = oneOf("ca.pem", "ca.crt"); err != nil {
134+
return "", "", "", err
135+
}
136+
if cert, err = oneOf("cert.pem", "tls.crt"); err != nil {
137+
return "", "", "", err
138+
}
139+
if key, err = oneOf("key.pem", "tls.key"); err != nil {
140+
return "", "", "", err
141+
}
142+
return caCert, cert, key, nil
143+
}

cmd/buildctl/common/common_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package common
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func writeTempFile(t *testing.T, dir, name, content string) string {
12+
t.Helper()
13+
path := filepath.Join(dir, name)
14+
require.NoError(t, os.WriteFile(path, []byte(content), 0644))
15+
return path
16+
}
17+
18+
func TestResolveTLSFilesFromDir(t *testing.T) {
19+
t.Run("all files present for cert-manager style", func(t *testing.T) {
20+
dir := t.TempDir()
21+
ca := writeTempFile(t, dir, "ca.crt", "ca")
22+
cert := writeTempFile(t, dir, "tls.crt", "cert")
23+
key := writeTempFile(t, dir, "tls.key", "key")
24+
25+
caOut, certOut, keyOut, err := resolveTLSFilesFromDir(dir)
26+
require.Equal(t, ca, caOut)
27+
require.Equal(t, cert, certOut)
28+
require.Equal(t, key, keyOut)
29+
require.NoError(t, err)
30+
})
31+
32+
t.Run("all files present for pem style", func(t *testing.T) {
33+
dir := t.TempDir()
34+
ca := writeTempFile(t, dir, "ca.pem", "ca")
35+
cert := writeTempFile(t, dir, "cert.pem", "cert")
36+
key := writeTempFile(t, dir, "key.pem", "key")
37+
38+
caOut, certOut, keyOut, err := resolveTLSFilesFromDir(dir)
39+
require.Equal(t, ca, caOut)
40+
require.Equal(t, cert, certOut)
41+
require.Equal(t, key, keyOut)
42+
require.NoError(t, err)
43+
})
44+
45+
t.Run("mixed set is present", func(t *testing.T) {
46+
dir := t.TempDir()
47+
ca := writeTempFile(t, dir, "ca.crt", "ca-cert-manager")
48+
cert := writeTempFile(t, dir, "cert.pem", "cert-pem")
49+
key := writeTempFile(t, dir, "key.pem", "key-pem")
50+
// ca for cert-manager, cert and key for pem
51+
52+
caOut, certOut, keyOut, err := resolveTLSFilesFromDir(dir)
53+
require.Equal(t, ca, caOut)
54+
require.Equal(t, cert, certOut)
55+
require.Equal(t, key, keyOut)
56+
require.NoError(t, err)
57+
})
58+
59+
t.Run("all files present for cert-manager and pem styles and pem is chosen", func(t *testing.T) {
60+
dir := t.TempDir()
61+
writeTempFile(t, dir, "ca.crt", "ca-cert-manager")
62+
writeTempFile(t, dir, "tls.crt", "cert-cert-manager")
63+
writeTempFile(t, dir, "tls.key", "key-cert-manager")
64+
ca := writeTempFile(t, dir, "ca.pem", "ca-pem")
65+
cert := writeTempFile(t, dir, "cert.pem", "cert-pem")
66+
key := writeTempFile(t, dir, "key.pem", "key-pem")
67+
68+
caOut, certOut, keyOut, err := resolveTLSFilesFromDir(dir)
69+
require.Equal(t, ca, caOut)
70+
require.Equal(t, cert, certOut)
71+
require.Equal(t, key, keyOut)
72+
require.NoError(t, err)
73+
})
74+
}

cmd/buildctl/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func main() {
8787
},
8888
cli.StringFlag{
8989
Name: "tlsdir",
90-
Usage: "directory containing CA certificate, client certificate, and client key",
90+
Usage: "directory containing CA certificate, client certificate, and client key. Supported file names are (ca.pem, cert.pem, key.pem) or (ca.crt, tls.crt, tls.key)",
9191
Value: "",
9292
},
9393
cli.IntFlag{

docs/reference/buildctl.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ GLOBAL OPTIONS:
2929
--tlscacert value CA certificate for validation
3030
--tlscert value client certificate
3131
--tlskey value client key
32-
--tlsdir value directory containing CA certificate, client certificate, and client key
32+
--tlsdir value directory containing CA certificate, client certificate, and client key. Supported file names are (ca.pem, cert.pem, key.pem) or (ca.crt, tls.crt, tls.key)
3333
--timeout value timeout backend connection after value seconds (default: 5)
3434
--wait block RPCs until the connection becomes available
3535
--help, -h show help

0 commit comments

Comments
 (0)