mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2025-12-23 14:25:50 +00:00
The release of Go 1.21.6 includes the new boring crypto when compiling with FIPS enabled. See https://go.dev/doc/devel/release#go1.21.0 and https://github.com/golang/go/issues/64717. This new version of boring crypto allows the use of TLS v1.3 for the first time, so we changed the Pinniped code to use TLS v1.3 where appropriate when compiled with the FIPS compiler. It also changed the allowed TLS v1.2 ciphers, so we updated those as well. After this commit, the project must be compiled by at least Go v1.21.6 when compiling in fips mode. The hack/Dockerfile_fips was already updated to use that version of Go in a previous commit. Co-authored-by: Benjamin A. Petersen <ben@benjaminapetersen.me>
145 lines
3.6 KiB
Go
145 lines
3.6 KiB
Go
// Copyright 2022-2024 the Pinniped contributors. All Rights Reserved.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package testlib
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"os/exec"
|
|
"regexp"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"go.pinniped.dev/internal/testutil/tlsserver"
|
|
)
|
|
|
|
func RunNmapSSLEnum(t *testing.T, host string, port uint16) (string, string) {
|
|
t.Helper()
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
|
defer cancel()
|
|
|
|
version, err := exec.CommandContext(ctx, "nmap", "-V").CombinedOutput()
|
|
require.NoError(t, err)
|
|
|
|
versionMatches := regexp.MustCompile(`Nmap version 7\.(?P<minor>\d+)`).FindStringSubmatch(string(version))
|
|
require.Len(t, versionMatches, 2)
|
|
minorVersion, err := strconv.Atoi(versionMatches[1])
|
|
require.NoError(t, err)
|
|
require.GreaterOrEqual(t, minorVersion, 92, "nmap >= 7.92.x is required")
|
|
|
|
var stdout, stderr bytes.Buffer
|
|
//nolint:gosec // we are not performing malicious argument injection against ourselves
|
|
cmd := exec.CommandContext(ctx, "nmap", "--script", "ssl-enum-ciphers",
|
|
"-p", strconv.FormatUint(uint64(port), 10),
|
|
host,
|
|
)
|
|
cmd.Stdout = &stdout
|
|
cmd.Stderr = &stderr
|
|
|
|
require.NoErrorf(t, cmd.Run(), "stderr:\n%s\n\nstdout:\n%s\n\n", stderr.String(), stdout.String())
|
|
|
|
return stdout.String(), stderr.String()
|
|
}
|
|
|
|
func GetExpectedCiphers(config *tls.Config) string {
|
|
skip12 := config.MinVersion == tls.VersionTLS13
|
|
skip13 := config.MaxVersion == tls.VersionTLS12
|
|
|
|
var tls12Bit, tls13Bit string
|
|
|
|
if !skip12 {
|
|
sort.SliceStable(config.CipherSuites, func(i, j int) bool {
|
|
a := tls.CipherSuiteName(config.CipherSuites[i])
|
|
b := tls.CipherSuiteName(config.CipherSuites[j])
|
|
|
|
ok1 := strings.Contains(a, "_ECDSA_")
|
|
ok2 := strings.Contains(b, "_ECDSA_")
|
|
|
|
if ok1 && ok2 {
|
|
return false
|
|
}
|
|
|
|
return ok1
|
|
})
|
|
|
|
var s strings.Builder
|
|
for i, id := range config.CipherSuites {
|
|
name := tls.CipherSuiteName(id)
|
|
group := ""
|
|
if strings.Contains(name, "_ECDHE_") {
|
|
group = secp256r1
|
|
} else {
|
|
group = rsa2048
|
|
}
|
|
s.WriteString(fmt.Sprintf(tls12Item, name, group))
|
|
if i == len(config.CipherSuites)-1 {
|
|
break
|
|
}
|
|
s.WriteString("\n")
|
|
}
|
|
tls12Bit = fmt.Sprintf(tls12Base, s.String(), cipherSuitePreference)
|
|
}
|
|
|
|
if !skip13 {
|
|
var s strings.Builder
|
|
tls13CipherSuites := tlsserver.GetExpectedTLS13Ciphers()
|
|
for i, id := range tls13CipherSuites {
|
|
s.WriteString(fmt.Sprintf(tls13Item,
|
|
strings.Replace(tls.CipherSuiteName(id), "TLS_", "TLS_AKE_WITH_", 1),
|
|
tlsserver.GetExpectedTLS13CipherNMapKeyExchangeInfoValue(id)),
|
|
)
|
|
if i == len(tls13CipherSuites)-1 {
|
|
break
|
|
}
|
|
s.WriteString("\n")
|
|
}
|
|
tls13Bit = fmt.Sprintf(tls13Base, s.String())
|
|
}
|
|
|
|
return fmt.Sprintf(baseItem, tls12Bit, tls13Bit)
|
|
}
|
|
|
|
const (
|
|
// this surrounds the tls 1.2 and 1.3 text in a way that guarantees that other TLS versions are not supported.
|
|
baseItem = `/tcp open unknown
|
|
| ssl-enum-ciphers: %s%s
|
|
|_ least strength: A
|
|
|
|
Nmap done: 1 IP address (1 host up) scanned in`
|
|
|
|
// cipher preference is a variable because in FIPS mode it is server
|
|
// but in normal mode it is client.
|
|
tls12Base = `
|
|
| TLSv1.2:
|
|
| ciphers:
|
|
%s
|
|
| compressors:
|
|
| NULL
|
|
| cipher preference: %s`
|
|
|
|
tls12Item = `| %s (%s) - A`
|
|
|
|
tls13Base = `
|
|
| TLSv1.3:
|
|
| ciphers:
|
|
%s
|
|
| cipher preference: server`
|
|
|
|
// This curve name is part of the output for each of our elliptic curve ciphers.
|
|
// secp256r1 is also known as P-256.
|
|
secp256r1 = "secp256r1"
|
|
// For the RSA ciphers, we expect this output to be RSA 2048.
|
|
rsa2048 = "rsa 2048"
|
|
|
|
tls13Item = `| %s (%s) - A`
|
|
)
|