Make 'tls_min_version' configurable

This commit is contained in:
vishalnayak 2016-07-12 19:32:47 -04:00
parent f200a8568b
commit ee6ba1e85e
7 changed files with 75 additions and 54 deletions

View file

@ -8,7 +8,9 @@ import (
"net/url"
"strings"
"github.com/fatih/structs"
"github.com/go-ldap/ldap"
"github.com/hashicorp/vault/helper/tlsutil"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
)
@ -71,6 +73,12 @@ func pathConfig(b *backend) *framework.Path {
Type: framework.TypeBool,
Description: "Issue a StartTLS command after establishing unencrypted connection (optional)",
},
"tls_min_version": &framework.FieldSchema{
Type: framework.TypeString,
Default: "tls12",
Description: "Minimum TLS version to use. Accepted values are 'tls10', 'tls11' or 'tls12'. Defaults to 'tls12'",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
@ -110,20 +118,14 @@ func (b *backend) pathConfigRead(
return nil, nil
}
// Convert the struct into a map
data := structs.New(cfg).Map()
// Convert the integer representing the TLS version into string of
// the form 'tls10', 'tls11' or 'tls12'
data["tls_min_version"] = tlsutil.TLSReverseLookup[data["tls_min_version"].(uint16)]
return &logical.Response{
Data: map[string]interface{}{
"url": cfg.Url,
"userdn": cfg.UserDN,
"groupdn": cfg.GroupDN,
"upndomain": cfg.UPNDomain,
"userattr": cfg.UserAttr,
"certificate": cfg.Certificate,
"insecure_tls": cfg.InsecureTLS,
"starttls": cfg.StartTLS,
"binddn": cfg.BindDN,
"bindpass": cfg.BindPassword,
"discoverdn": cfg.DiscoverDN,
},
Data: data,
}, nil
}
@ -159,6 +161,14 @@ func (b *backend) pathConfigWrite(
if insecureTLS {
cfg.InsecureTLS = insecureTLS
}
tlsMinVersion := d.Get("tls_min_version").(string)
if tlsMinVersion != "" {
var ok bool
cfg.TLSMinVersion, ok = tlsutil.TLSLookup[tlsMinVersion]
if !ok {
return logical.ErrorResponse("failed to set 'tls_min_version'"), nil
}
}
startTLS := d.Get("starttls").(bool)
if startTLS {
cfg.StartTLS = startTLS
@ -200,22 +210,23 @@ func (b *backend) pathConfigWrite(
}
type ConfigEntry struct {
Url string
UserDN string
GroupDN string
UPNDomain string
UserAttr string
Certificate string
InsecureTLS bool
StartTLS bool
BindDN string
BindPassword string
DiscoverDN bool
Url string `json:"url" structs:"url" mapstructure:"url"`
UserDN string `json:"userdn" structs:"userdn" mapstructure:"userdn"`
GroupDN string `json:"groupdn" structs:"groupdn" mapstructure:"groupdn"`
UPNDomain string `json:"upndomain" structs:"upndomain" mapstructure:"upndomain"`
UserAttr string `json:"userattr" structs:"userattr" mapstructure:"userattr"`
Certificate string `json:"certificate" structs:"certificate" mapstructure:"certificate"`
InsecureTLS bool `json:"insecure_tls" structs:"insecure_tls" mapstructure:"insecure_tls"`
StartTLS bool `json:"starttls" structs:"starttls" mapstructure:"starttls"`
BindDN string `json:"binddn" structs:"binddn" mapstructure:"binddn"`
BindPassword string `json:"bindpass" structs:"bindpass" mapstructure:"bindpass"`
DiscoverDN bool `json:"discoverdn" structs:"discoverdn" mapstructure:"discoverdn"`
TLSMinVersion uint16 `json:"tls_min_version" structs:"tls_min_version" mapstructure:"tls_min_version"`
}
func (c *ConfigEntry) GetTLSConfig(host string) (*tls.Config, error) {
tlsConfig := &tls.Config{
MinVersion: VersionTLS12,
MinVersion: c.TLSMinVersion,
ServerName: host,
}
if c.InsecureTLS {

View file

@ -46,16 +46,17 @@ type backend struct {
}
type sessionConfig struct {
Hosts string `json:"hosts" structs:"hosts"`
Username string `json:"username" structs:"username"`
Password string `json:"password" structs:"password"`
TLS bool `json:"tls" structs:"tls"`
InsecureTLS bool `json:"insecure_tls" structs:"insecure_tls"`
Certificate string `json:"certificate" structs:"certificate"`
PrivateKey string `json:"private_key" structs:"private_key"`
IssuingCA string `json:"issuing_ca" structs:"issuing_ca"`
ProtocolVersion int `json:"protocol_version" structs:"protocol_version"`
ConnectTimeout int `json:"connect_timeout" structs:"connect_timeout"`
Hosts string `json:"hosts" structs:"hosts" mapstructure:"hosts"`
Username string `json:"username" structs:"username" mapstructure:"username"`
Password string `json:"password" structs:"password" mapstructure:"password"`
TLS bool `json:"tls" structs:"tls" mapstructure:"tls"`
InsecureTLS bool `json:"insecure_tls" structs:"insecure_tls" mapstructure:"insecure_tls"`
Certificate string `json:"certificate" structs:"certificate" mapstructure:"certificate"`
PrivateKey string `json:"private_key" structs:"private_key" mapstructure:"private_key"`
IssuingCA string `json:"issuing_ca" structs:"issuing_ca" mapstructure:"issuing_ca"`
ProtocolVersion int `json:"protocol_version" structs:"protocol_version" mapstructure:"protocol_version"`
ConnectTimeout int `json:"connect_timeout" structs:"connect_timeout" mapstructure:"connect_timeout"`
TLSMinVersion uint16 `json:"tls_min_version" structs:"tls_min_version" mapstructure:"tls_min_version"`
}
// DB returns the database connection.

View file

@ -5,6 +5,7 @@ import (
"github.com/fatih/structs"
"github.com/hashicorp/vault/helper/certutil"
"github.com/hashicorp/vault/helper/tlsutil"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
)
@ -40,6 +41,12 @@ set, this is automatically set to true`,
effect if a CA certificate is provided`,
},
"tls_min_version": &framework.FieldSchema{
Type: framework.TypeString,
Default: "tls12",
Description: "Minimum TLS version to use. Accepted values are 'tls10', 'tls11' or 'tls12'. Defaults to 'tls12'",
},
"pem_bundle": &framework.FieldSchema{
Type: framework.TypeString,
Description: `PEM-format, concatenated unencrypted secret key
@ -98,8 +105,9 @@ func (b *backend) pathConnectionRead(
config.PrivateKey = "**********"
}
d := structs.New(config).Map()
return &logical.Response{
Data: structs.New(config).Map(),
Data: d,
}, nil
}
@ -128,6 +136,15 @@ func (b *backend) pathConnectionWrite(
ConnectTimeout: data.Get("connect_timeout").(int),
}
tlsMinVersion := data.Get("tls_min_version").(string)
if tlsMinVersion != "" {
var ok bool
config.TLSMinVersion, ok = tlsutil.TLSLookup[tlsMinVersion]
if !ok {
return logical.ErrorResponse("failed to set 'tls_min_version'"), nil
}
}
if config.InsecureTLS {
config.TLS = true
}

View file

@ -48,11 +48,7 @@ func createSession(cfg *sessionConfig, s logical.Storage) (*gocql.Session, error
clusterConfig.Timeout = time.Duration(cfg.ConnectTimeout) * time.Second
if cfg.TLS {
tlsConfig := &tls.Config{
InsecureSkipVerify: cfg.InsecureTLS,
MinVersion: VersionTLS12,
}
var tlsConfig *tls.Config
if len(cfg.Certificate) > 0 || len(cfg.IssuingCA) > 0 {
if len(cfg.Certificate) > 0 && len(cfg.PrivateKey) == 0 {
return nil, fmt.Errorf("Found certificate for TLS authentication but no private key")
@ -65,18 +61,19 @@ func createSession(cfg *sessionConfig, s logical.Storage) (*gocql.Session, error
}
if len(cfg.IssuingCA) > 0 {
certBundle.IssuingCA = cfg.IssuingCA
tlsConfig.InsecureSkipVerify = false
}
parsedCertBundle, err := certBundle.ToParsedCertBundle()
if err != nil {
return nil, fmt.Errorf("Error parsing certificate bundle: %s", err)
return nil, fmt.Errorf("failed to parse certificate bundle: %s", err)
}
tlsConfig, err = parsedCertBundle.GetTLSConfig(certutil.TLSClient)
if err != nil {
return nil, fmt.Errorf("Error getting TLS configuration: %s", err)
return nil, fmt.Errorf("failed to get TLS configuration: %s", err)
}
tlsConfig.InsecureSkipVerify = cfg.InsecureTLS
tlsConfig.MinVersion = cfg.TLSMinVersion
}
clusterConfig.SslOpts = &gocql.SslOptions{

View file

@ -10,6 +10,8 @@ import (
"net"
"strconv"
"sync"
"github.com/hashicorp/vault/helper/tlsutil"
)
// ListenerFactory is the factory function to create a listener.
@ -21,13 +23,6 @@ var BuiltinListeners = map[string]ListenerFactory{
"atlas": atlasListenerFactory,
}
// tlsLookup maps the tls_min_version configuration to the internal value
var tlsLookup = map[string]uint16{
"tls10": tls.VersionTLS10,
"tls11": tls.VersionTLS11,
"tls12": tls.VersionTLS12,
}
// NewListener creates a new listener of the given type with the given
// configuration. The type is looked up in the BuiltinListeners map.
func NewListener(t string, config map[string]string, logger io.Writer) (net.Listener, map[string]string, ReloadFunc, error) {
@ -81,7 +76,7 @@ func listenerWrapTLS(
tlsConf := &tls.Config{}
tlsConf.GetCertificate = cg.getCertificate
tlsConf.NextProtos = []string{"http/1.1"}
tlsConf.MinVersion, ok = tlsLookup[tlsvers]
tlsConf.MinVersion, ok = tlsutil.TLSLookup[tlsvers]
if !ok {
return nil, nil, nil, fmt.Errorf("'tls_min_version' value %s not supported, please specify one of [tls10,tls11,tls12]", tlsvers)
}

View file

@ -438,7 +438,7 @@ func (p *ParsedCertBundle) GetTLSConfig(usage TLSUsage) (*tls.Config, error) {
tlsConfig := &tls.Config{
NextProtos: []string{"http/1.1"},
MinVersion: VersionTLS12,
MinVersion: tls.VersionTLS12,
}
if p.Certificate != nil {

View file

@ -191,7 +191,7 @@ func setupTLSConfig(conf map[string]string) (*tls.Config, error) {
}
tlsClientConfig := &tls.Config{
MinVersion: VersionTLS12,
MinVersion: tls.VersionTLS12,
InsecureSkipVerify: insecureSkipVerify,
ServerName: serverName[0],
}