diff options
Diffstat (limited to 'internal/tlsconfig/tlsconfig.go')
-rw-r--r-- | internal/tlsconfig/tlsconfig.go | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/internal/tlsconfig/tlsconfig.go b/internal/tlsconfig/tlsconfig.go new file mode 100644 index 00000000..1c9db71e --- /dev/null +++ b/internal/tlsconfig/tlsconfig.go @@ -0,0 +1,105 @@ +package tlsconfig + +import ( + "crypto/tls" + "fmt" + "os" + "sort" + "strings" +) + +// GetCertificateFunc returns the certificate to be used for given domain +type GetCertificateFunc func(*tls.ClientHelloInfo) (*tls.Certificate, error) + +var ( + preferredCipherSuites = []uint16{ + tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + } + + // AllTLSVersions has all supported flag values + AllTLSVersions = map[string]uint16{ + "": 0, // Default value in tls.Config + "ssl3": tls.VersionSSL30, + "tls1.0": tls.VersionTLS10, + "tls1.1": tls.VersionTLS11, + "tls1.2": tls.VersionTLS12, + } +) + +// FlagUsage returns string with explanation how to use the CLI flag +func FlagUsage(minOrMax string) string { + versions := []string{} + + for version := range AllTLSVersions { + if version != "" { + versions = append(versions, fmt.Sprintf("%q", version)) + } + } + sort.Strings(versions) + + return fmt.Sprintf("Specifies the "+minOrMax+"imum SSL/TLS version, supported values are %s", strings.Join(versions, ", ")) +} + +// Create returns tls.Config for given app configuration +func Create(cert, key []byte, getCertificate GetCertificateFunc, insecureCiphers bool, tlsMinVersion uint16, tlsMaxVersion uint16) (*tls.Config, error) { + tlsConfig := &tls.Config{GetCertificate: getCertificate} + + err := configureCertificate(tlsConfig, cert, key) + if err != nil { + return nil, err + } + + if !insecureCiphers { + configureTLSCiphers(tlsConfig) + } + + tlsConfig.MinVersion = tlsMinVersion + tlsConfig.MaxVersion = tlsMaxVersion + + return tlsConfig, nil +} + +// ValidateTLSVersions returns error if the provided TLS versions config values are not valid +func ValidateTLSVersions(min, max string) error { + tlsMin, tlsMinOk := AllTLSVersions[min] + tlsMax, tlsMaxOk := AllTLSVersions[max] + + if !tlsMinOk { + return fmt.Errorf("Invalid minimum TLS version: %s", min) + } + if !tlsMaxOk { + return fmt.Errorf("Invalid maximum TLS version: %s", max) + } + if tlsMin > tlsMax && tlsMax > 0 { + return fmt.Errorf("Invalid maximum TLS version: %s; Should be at least %s", max, min) + } + + // At this point values are validated so if we have tls1.3 + // accepted we are on Go 1.12+ so let's enable it too. + if min == "tls1.3" || max == "tls1.3" { + os.Setenv("GODEBUG", os.Getenv("GODEBUG")+",tls13=1") + } + + return nil +} + +func configureCertificate(tlsConfig *tls.Config, cert, key []byte) error { + certificate, err := tls.X509KeyPair(cert, key) + if err != nil { + return err + } + + tlsConfig.Certificates = []tls.Certificate{certificate} + + return nil +} + +func configureTLSCiphers(tlsConfig *tls.Config) { + tlsConfig.PreferServerCipherSuites = true + tlsConfig.CipherSuites = preferredCipherSuites +} |