mirror of
https://github.com/status-im/consul.git
synced 2025-01-09 21:35:52 +00:00
5fb9df1640
* Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Updating the license from MPL to Business Source License Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at <Blog URL>, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl. * add missing license headers * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
232 lines
7.9 KiB
Go
232 lines
7.9 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package types
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// TLSVersion is a strongly-typed string for TLS versions
|
|
type TLSVersion string
|
|
|
|
const (
|
|
// Error value, excluded from lookup maps
|
|
TLSVersionInvalid TLSVersion = "TLS_INVALID"
|
|
|
|
// Explicit unspecified zero-value to avoid overwriting parent defaults
|
|
TLSVersionUnspecified TLSVersion = ""
|
|
|
|
// Explictly allow implementation to select TLS version
|
|
// May be useful to supercede defaults specified at a higher layer
|
|
TLSVersionAuto TLSVersion = "TLS_AUTO"
|
|
|
|
_ // Placeholder for SSLv3, hopefully we won't have to add this
|
|
|
|
// TLS versions
|
|
TLSv1_0 TLSVersion = "TLSv1_0"
|
|
TLSv1_1 TLSVersion = "TLSv1_1"
|
|
TLSv1_2 TLSVersion = "TLSv1_2"
|
|
TLSv1_3 TLSVersion = "TLSv1_3"
|
|
)
|
|
|
|
var (
|
|
tlsVersions = map[TLSVersion]struct{}{
|
|
TLSVersionAuto: {},
|
|
TLSv1_0: {},
|
|
TLSv1_1: {},
|
|
TLSv1_2: {},
|
|
TLSv1_3: {},
|
|
}
|
|
// NOTE: This interface is deprecated in favor of tlsVersions
|
|
// and should be eventually removed in a future release.
|
|
DeprecatedConsulAgentTLSVersions = map[string]TLSVersion{
|
|
"": TLSVersionAuto,
|
|
"tls10": TLSv1_0,
|
|
"tls11": TLSv1_1,
|
|
"tls12": TLSv1_2,
|
|
"tls13": TLSv1_3,
|
|
}
|
|
// NOTE: these currently map to the deprecated config strings to support the
|
|
// deployment pattern of upgrading servers first. This map should eventually
|
|
// be removed and any lookups updated to instead use the TLSVersion string
|
|
// values directly in a future release.
|
|
ConsulAutoConfigTLSVersionStrings = map[TLSVersion]string{
|
|
TLSVersionAuto: "",
|
|
TLSv1_0: "tls10",
|
|
TLSv1_1: "tls11",
|
|
TLSv1_2: "tls12",
|
|
TLSv1_3: "tls13",
|
|
}
|
|
TLSVersionsWithConfigurableCipherSuites = map[TLSVersion]struct{}{
|
|
// NOTE: these two are implementation-dependent, but it is not expected that
|
|
// either Go or Envoy would default to TLS 1.3 as a minimum version in the
|
|
// near future
|
|
TLSVersionUnspecified: {},
|
|
TLSVersionAuto: {},
|
|
|
|
TLSv1_0: {},
|
|
TLSv1_1: {},
|
|
TLSv1_2: {},
|
|
}
|
|
)
|
|
|
|
func (v *TLSVersion) String() string {
|
|
return string(*v)
|
|
}
|
|
|
|
var tlsVersionComparison = map[TLSVersion]uint{
|
|
TLSv1_0: 1,
|
|
TLSv1_1: 2,
|
|
TLSv1_2: 3,
|
|
TLSv1_3: 4,
|
|
}
|
|
|
|
// Will only return true for concrete versions and won't catch
|
|
// implementation-dependent conflicts with TLSVersionAuto or unspecified values
|
|
func (a TLSVersion) LessThan(b TLSVersion) (error, bool) {
|
|
for _, v := range []TLSVersion{a, b} {
|
|
if _, ok := tlsVersionComparison[v]; !ok {
|
|
return fmt.Errorf("can't compare implementation-dependent values"), false
|
|
}
|
|
}
|
|
|
|
return nil, tlsVersionComparison[a] < tlsVersionComparison[b]
|
|
}
|
|
|
|
func TLSVersions() string {
|
|
versions := []string{}
|
|
for v := range tlsVersions {
|
|
versions = append(versions, string(v))
|
|
}
|
|
sort.Strings(versions)
|
|
|
|
return strings.Join(versions, ", ")
|
|
}
|
|
|
|
func ValidateTLSVersion(v TLSVersion) error {
|
|
if _, ok := tlsVersions[v]; !ok {
|
|
return fmt.Errorf("no matching TLS version found for %s, please specify one of [%s]", v.String(), TLSVersions())
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// IANA cipher suite string constants as defined at
|
|
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
|
|
// This is the total list of TLS 1.2-style cipher suites
|
|
// which are currently supported by either Envoy 1.21 or the Consul agent
|
|
// via Go, and may change as some older suites are removed in future
|
|
// Envoy releases and Consul drops support for older Envoy versions,
|
|
// and as supported cipher suites in the Go runtime change.
|
|
//
|
|
// The naming convention for cipher suites changed in TLS 1.3
|
|
// but constant values should still be globally unqiue.
|
|
//
|
|
// Handling validation on distinct sets of TLS 1.3 and TLS 1.2 TLSCipherSuite
|
|
// constants would be a future exercise if cipher suites for TLS 1.3 ever
|
|
// become configurable in BoringSSL, Envoy, or other implementation.
|
|
type TLSCipherSuite string
|
|
|
|
const (
|
|
// Cipher suites used by both Envoy and Consul agent
|
|
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"
|
|
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
|
|
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
|
|
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
|
|
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"
|
|
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
|
|
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
|
|
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
|
|
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"
|
|
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"
|
|
|
|
// Older cipher suites not supported for Consul agent TLS,
|
|
// will eventually be removed from Envoy defaults
|
|
TLS_RSA_WITH_AES_128_GCM_SHA256 = "TLS_RSA_WITH_AES_128_GCM_SHA256"
|
|
TLS_RSA_WITH_AES_128_CBC_SHA = "TLS_RSA_WITH_AES_128_CBC_SHA"
|
|
TLS_RSA_WITH_AES_256_GCM_SHA384 = "TLS_RSA_WITH_AES_256_GCM_SHA384"
|
|
TLS_RSA_WITH_AES_256_CBC_SHA = "TLS_RSA_WITH_AES_256_CBC_SHA"
|
|
)
|
|
|
|
var (
|
|
consulAgentTLSCipherSuites = map[TLSCipherSuite]struct{}{
|
|
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: {},
|
|
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: {},
|
|
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: {},
|
|
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: {},
|
|
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: {},
|
|
|
|
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: {},
|
|
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: {},
|
|
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: {},
|
|
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: {},
|
|
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: {},
|
|
}
|
|
envoyTLSCipherSuiteStrings = map[TLSCipherSuite]string{
|
|
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "ECDHE-ECDSA-AES128-GCM-SHA256",
|
|
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: "ECDHE-ECDSA-CHACHA20-POLY1305",
|
|
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: "ECDHE-RSA-AES128-GCM-SHA256",
|
|
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: "ECDHE-RSA-CHACHA20-POLY1305",
|
|
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: "ECDHE-ECDSA-AES128-SHA",
|
|
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: "ECDHE-RSA-AES128-SHA",
|
|
TLS_RSA_WITH_AES_128_GCM_SHA256: "AES128-GCM-SHA256",
|
|
TLS_RSA_WITH_AES_128_CBC_SHA: "AES128-SHA",
|
|
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: "ECDHE-ECDSA-AES256-GCM-SHA384",
|
|
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: "ECDHE-RSA-AES256-GCM-SHA384",
|
|
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: "ECDHE-ECDSA-AES256-SHA",
|
|
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: "ECDHE-RSA-AES256-SHA",
|
|
TLS_RSA_WITH_AES_256_GCM_SHA384: "AES256-GCM-SHA384",
|
|
TLS_RSA_WITH_AES_256_CBC_SHA: "AES256-SHA",
|
|
}
|
|
)
|
|
|
|
func (c *TLSCipherSuite) String() string {
|
|
return string(*c)
|
|
}
|
|
|
|
func ValidateConsulAgentCipherSuites(cipherSuites []TLSCipherSuite) error {
|
|
var unmatched []string
|
|
|
|
for _, c := range cipherSuites {
|
|
if _, ok := consulAgentTLSCipherSuites[c]; !ok {
|
|
unmatched = append(unmatched, c.String())
|
|
}
|
|
}
|
|
|
|
if len(unmatched) > 0 {
|
|
return fmt.Errorf("no matching Consul Agent TLS cipher suite found for %s", strings.Join(unmatched, ","))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func ValidateEnvoyCipherSuites(cipherSuites []TLSCipherSuite) error {
|
|
var unmatched []string
|
|
|
|
for _, c := range cipherSuites {
|
|
if _, ok := envoyTLSCipherSuiteStrings[c]; !ok {
|
|
unmatched = append(unmatched, c.String())
|
|
}
|
|
}
|
|
|
|
if len(unmatched) > 0 {
|
|
return fmt.Errorf("no matching Envoy TLS cipher suite found for %s", strings.Join(unmatched, ","))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func MarshalEnvoyTLSCipherSuiteStrings(cipherSuites []TLSCipherSuite) []string {
|
|
cipherSuiteStrings := []string{}
|
|
|
|
for _, c := range cipherSuites {
|
|
if s, ok := envoyTLSCipherSuiteStrings[c]; ok {
|
|
cipherSuiteStrings = append(cipherSuiteStrings, s)
|
|
}
|
|
}
|
|
|
|
return cipherSuiteStrings
|
|
}
|