mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add configurable cipher suites for tls listening (#10505)
* feat: add configurable cipher suites for tls listening * tls.VersionName is go 1.21, copy the function
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cdr.dev/slog"
|
||||
"cdr.dev/slog/sloggers/sloghuman"
|
||||
)
|
||||
|
||||
func Test_configureCipherSuites(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cipherNames := func(ciphers []*tls.CipherSuite) []string {
|
||||
var names []string
|
||||
for _, c := range ciphers {
|
||||
names = append(names, c.Name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
cipherIDs := func(ciphers []*tls.CipherSuite) []uint16 {
|
||||
var ids []uint16
|
||||
for _, c := range ciphers {
|
||||
ids = append(ids, c.ID)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
cipherByName := func(cipher string) *tls.CipherSuite {
|
||||
for _, c := range append(tls.CipherSuites(), tls.InsecureCipherSuites()...) {
|
||||
if cipher == c.Name {
|
||||
c := c
|
||||
return c
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
wantErr string
|
||||
wantWarnings []string
|
||||
inputCiphers []string
|
||||
minTLS uint16
|
||||
maxTLS uint16
|
||||
allowInsecure bool
|
||||
expectCiphers []uint16
|
||||
}{
|
||||
{
|
||||
name: "AllSecure",
|
||||
minTLS: tls.VersionTLS10,
|
||||
maxTLS: tls.VersionTLS13,
|
||||
inputCiphers: cipherNames(tls.CipherSuites()),
|
||||
wantWarnings: []string{},
|
||||
expectCiphers: cipherIDs(tls.CipherSuites()),
|
||||
},
|
||||
{
|
||||
name: "AllowInsecure",
|
||||
minTLS: tls.VersionTLS10,
|
||||
maxTLS: tls.VersionTLS13,
|
||||
inputCiphers: append(cipherNames(tls.CipherSuites()), tls.InsecureCipherSuites()[0].Name),
|
||||
allowInsecure: true,
|
||||
wantWarnings: []string{
|
||||
"insecure tls cipher specified",
|
||||
},
|
||||
expectCiphers: append(cipherIDs(tls.CipherSuites()), tls.InsecureCipherSuites()[0].ID),
|
||||
},
|
||||
{
|
||||
name: "AllInsecure",
|
||||
minTLS: tls.VersionTLS10,
|
||||
maxTLS: tls.VersionTLS13,
|
||||
inputCiphers: append(cipherNames(tls.CipherSuites()), cipherNames(tls.InsecureCipherSuites())...),
|
||||
allowInsecure: true,
|
||||
wantWarnings: []string{
|
||||
"insecure tls cipher specified",
|
||||
},
|
||||
expectCiphers: append(cipherIDs(tls.CipherSuites()), cipherIDs(tls.InsecureCipherSuites())...),
|
||||
},
|
||||
{
|
||||
// Providing ciphers that are not compatible with any tls version
|
||||
// enabled should generate a warning.
|
||||
name: "ExcessiveCiphers",
|
||||
minTLS: tls.VersionTLS10,
|
||||
maxTLS: tls.VersionTLS11,
|
||||
inputCiphers: []string{
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||
// Only for TLS 1.3
|
||||
"TLS_AES_128_GCM_SHA256",
|
||||
},
|
||||
allowInsecure: true,
|
||||
wantWarnings: []string{
|
||||
"cipher not supported for tls versions",
|
||||
},
|
||||
expectCiphers: cipherIDs([]*tls.CipherSuite{
|
||||
cipherByName("TLS_RSA_WITH_AES_128_CBC_SHA"),
|
||||
cipherByName("TLS_AES_128_GCM_SHA256"),
|
||||
}),
|
||||
},
|
||||
// Errors
|
||||
{
|
||||
name: "NotRealCiphers",
|
||||
minTLS: tls.VersionTLS10,
|
||||
maxTLS: tls.VersionTLS13,
|
||||
inputCiphers: []string{"RSA-Fake"},
|
||||
wantErr: "unsupported tls ciphers",
|
||||
},
|
||||
{
|
||||
name: "NoCiphers",
|
||||
minTLS: tls.VersionTLS10,
|
||||
maxTLS: tls.VersionTLS13,
|
||||
wantErr: "no tls ciphers supported",
|
||||
},
|
||||
{
|
||||
name: "InsecureNotAllowed",
|
||||
minTLS: tls.VersionTLS10,
|
||||
maxTLS: tls.VersionTLS13,
|
||||
inputCiphers: append(cipherNames(tls.CipherSuites()), tls.InsecureCipherSuites()[0].Name),
|
||||
wantErr: "insecure tls ciphers specified",
|
||||
},
|
||||
{
|
||||
name: "TLS1.3",
|
||||
minTLS: tls.VersionTLS13,
|
||||
maxTLS: tls.VersionTLS13,
|
||||
inputCiphers: cipherNames(tls.CipherSuites()),
|
||||
wantErr: "'--tls-ciphers' cannot be specified when using minimum tls version 1.3",
|
||||
},
|
||||
{
|
||||
name: "TLSUnsupported",
|
||||
minTLS: tls.VersionTLS10,
|
||||
maxTLS: tls.VersionTLS13,
|
||||
// TLS_RSA_WITH_AES_128_GCM_SHA256 only supports tls 1.2
|
||||
inputCiphers: []string{"TLS_RSA_WITH_AES_128_GCM_SHA256"},
|
||||
wantErr: "no tls ciphers supported for tls versions",
|
||||
},
|
||||
{
|
||||
name: "Min>Max",
|
||||
minTLS: tls.VersionTLS13,
|
||||
maxTLS: tls.VersionTLS12,
|
||||
wantErr: "minimum tls version (TLS 1.3) cannot be greater than maximum tls version (TLS 1.2)",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
var out bytes.Buffer
|
||||
logger := slog.Make(sloghuman.Sink(&out))
|
||||
|
||||
found, err := configureCipherSuites(ctx, logger, tt.inputCiphers, tt.allowInsecure, tt.minTLS, tt.maxTLS)
|
||||
if tt.wantErr != "" {
|
||||
require.ErrorContains(t, err, tt.wantErr)
|
||||
} else {
|
||||
require.NoError(t, err, "no error")
|
||||
require.ElementsMatch(t, tt.expectCiphers, found, "expected ciphers")
|
||||
if len(tt.wantWarnings) > 0 {
|
||||
logger.Sync()
|
||||
for _, w := range tt.wantWarnings {
|
||||
assert.Contains(t, out.String(), w, "expected warning")
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user