# Skip TLS certificate name verification.
InsecureTLS: false
+ # Mininum TLS version to negotiate when connecting to server
+ # (ldaps://... or StartTLS). It may be necessary to set this
+ # to "1.1" for compatibility with older LDAP servers. If
+ # blank, use the recommended minimum version (1.2).
+ MinTLSVersion: ""
+
# Strip the @domain part if a user supplies an email-style
# username with this domain. If "*", strip any user-provided
# domain. If "", never strip the domain part. Example:
"Login.LDAP.EmailAttribute": false,
"Login.LDAP.Enable": true,
"Login.LDAP.InsecureTLS": false,
+ "Login.LDAP.MinTLSVersion": false,
"Login.LDAP.SearchAttribute": false,
"Login.LDAP.SearchBase": false,
"Login.LDAP.SearchBindPassword": false,
}
log = log.WithField("URL", conf.URL.String())
- l, err := ldap.DialURL(conf.URL.String())
+ var l *ldap.Conn
+ var err error
+ if conf.URL.Scheme == "ldaps" {
+ // ldap.DialURL does not currently allow us to control
+ // tls.Config, so we need to figure out the port
+ // ourselves and call DialTLS.
+ host, port, err := net.SplitHostPort(conf.URL.Host)
+ if err != nil {
+ // Assume error means no port given
+ host = conf.URL.Host
+ port = ldap.DefaultLdapsPort
+ }
+ l, err = ldap.DialTLS("tcp", net.JoinHostPort(host, port), &tls.Config{
+ ServerName: host,
+ MinVersion: uint16(conf.MinTLSVersion),
+ })
+ } else {
+ l, err = ldap.DialURL(conf.URL.String())
+ }
if err != nil {
log.WithError(err).Error("ldap connection failed")
return arvados.APIClientAuthorization{}, err
var tlsconfig tls.Config
if conf.InsecureTLS {
tlsconfig.InsecureSkipVerify = true
+ tlsconfig.MinVersion = uint16(conf.MinTLSVersion)
} else {
if host, _, err := net.SplitHostPort(conf.URL.Host); err != nil {
// Assume SplitHostPort error means
package arvados
import (
+ "crypto/tls"
"encoding/json"
"errors"
"fmt"
URL URL
StartTLS bool
InsecureTLS bool
+ MinTLSVersion TLSVersion
StripDomain string
AppendDomain string
SearchAttribute string
return (*url.URL)(&su).String()
}
+type TLSVersion uint16
+
+func (v TLSVersion) MarshalText() ([]byte, error) {
+ switch v {
+ case 0:
+ return []byte{}, nil
+ case tls.VersionTLS10:
+ return []byte("1.0"), nil
+ case tls.VersionTLS11:
+ return []byte("1.1"), nil
+ case tls.VersionTLS12:
+ return []byte("1.2"), nil
+ case tls.VersionTLS13:
+ return []byte("1.3"), nil
+ default:
+ return nil, fmt.Errorf("unsupported TLSVersion %x", v)
+ }
+}
+
+func (v *TLSVersion) UnmarshalJSON(text []byte) error {
+ if len(text) > 0 && text[0] == '"' {
+ var s string
+ err := json.Unmarshal(text, &s)
+ if err != nil {
+ return err
+ }
+ text = []byte(s)
+ }
+ switch string(text) {
+ case "":
+ *v = 0
+ case "1.0":
+ *v = tls.VersionTLS10
+ case "1.1":
+ *v = tls.VersionTLS11
+ case "1.2":
+ *v = tls.VersionTLS12
+ case "1.3":
+ *v = tls.VersionTLS13
+ default:
+ return fmt.Errorf("unsupported TLSVersion %q", text)
+ }
+ return nil
+}
+
type ServiceInstance struct {
ListenURL URL
Rendezvous string `json:",omitempty"`
package arvados
import (
+ "crypto/tls"
"encoding/json"
"github.com/ghodss/yaml"
json.Unmarshal([]byte(`{"https://foo.example/": true}`), &b)
c.Check(a, check.DeepEquals, b)
}
+
+func (s *ConfigSuite) TestTLSVersion(c *check.C) {
+ var v struct {
+ Version TLSVersion
+ }
+ err := json.Unmarshal([]byte(`{"Version": 1.0}`), &v)
+ c.Check(err, check.IsNil)
+ c.Check(v.Version, check.Equals, TLSVersion(tls.VersionTLS10))
+
+ err = json.Unmarshal([]byte(`{"Version": "1.3"}`), &v)
+ c.Check(err, check.IsNil)
+ c.Check(v.Version, check.Equals, TLSVersion(tls.VersionTLS13))
+
+ err = json.Unmarshal([]byte(`{"Version": "1.345"}`), &v)
+ c.Check(err, check.NotNil)
+}