github.com/blixtra/nomad@v0.7.2-0.20171221000451-da9a1d7bb050/nomad/structs/config/tls.go (about) 1 package config 2 3 import ( 4 "crypto/tls" 5 "fmt" 6 "sync" 7 ) 8 9 // TLSConfig provides TLS related configuration 10 type TLSConfig struct { 11 12 // EnableHTTP enabled TLS for http traffic to the Nomad server and clients 13 EnableHTTP bool `mapstructure:"http"` 14 15 // EnableRPC enables TLS for RPC and Raft traffic to the Nomad servers 16 EnableRPC bool `mapstructure:"rpc"` 17 18 // VerifyServerHostname is used to enable hostname verification of servers. This 19 // ensures that the certificate presented is valid for server.<region>.nomad 20 // This prevents a compromised client from being restarted as a server, and then 21 // intercepting request traffic as well as being added as a raft peer. This should be 22 // enabled by default with VerifyOutgoing, but for legacy reasons we cannot break 23 // existing clients. 24 VerifyServerHostname bool `mapstructure:"verify_server_hostname"` 25 26 // CAFile is a path to a certificate authority file. This is used with VerifyIncoming 27 // or VerifyOutgoing to verify the TLS connection. 28 CAFile string `mapstructure:"ca_file"` 29 30 // CertFile is used to provide a TLS certificate that is used for serving TLS connections. 31 // Must be provided to serve TLS connections. 32 CertFile string `mapstructure:"cert_file"` 33 34 // KeyLoader is a helper to dynamically reload TLS configuration 35 KeyLoader *KeyLoader 36 37 keyloaderLock sync.Mutex 38 39 // KeyFile is used to provide a TLS key that is used for serving TLS connections. 40 // Must be provided to serve TLS connections. 41 KeyFile string `mapstructure:"key_file"` 42 43 // RPCUpgradeMode should be enabled when a cluster is being upgraded 44 // to TLS. Allows servers to accept both plaintext and TLS connections and 45 // should only be a temporary state. 46 RPCUpgradeMode bool `mapstructure:"rpc_upgrade_mode"` 47 48 // Verify connections to the HTTPS API 49 VerifyHTTPSClient bool `mapstructure:"verify_https_client"` 50 } 51 52 type KeyLoader struct { 53 cacheLock sync.Mutex 54 certificate *tls.Certificate 55 } 56 57 // LoadKeyPair reloads the TLS certificate based on the specified certificate 58 // and key file. If successful, stores the certificate for further use. 59 func (k *KeyLoader) LoadKeyPair(certFile, keyFile string) (*tls.Certificate, error) { 60 k.cacheLock.Lock() 61 defer k.cacheLock.Unlock() 62 63 // Allow downgrading 64 if certFile == "" && keyFile == "" { 65 k.certificate = nil 66 return nil, nil 67 } 68 69 cert, err := tls.LoadX509KeyPair(certFile, keyFile) 70 if err != nil { 71 return nil, fmt.Errorf("Failed to load cert/key pair: %v", err) 72 } 73 74 k.certificate = &cert 75 return k.certificate, nil 76 } 77 78 // GetOutgoingCertificate fetches the currently-loaded certificate when 79 // accepting a TLS connection. This currently does not consider information in 80 // the ClientHello and only returns the certificate that was last loaded. 81 func (k *KeyLoader) GetOutgoingCertificate(*tls.ClientHelloInfo) (*tls.Certificate, error) { 82 k.cacheLock.Lock() 83 defer k.cacheLock.Unlock() 84 return k.certificate, nil 85 } 86 87 // GetClientCertificate fetches the currently-loaded certificate when the Server 88 // requests a certificate from the caller. This currently does not consider 89 // information in the ClientHello and only returns the certificate that was last 90 // loaded. 91 func (k *KeyLoader) GetClientCertificate(*tls.CertificateRequestInfo) (*tls.Certificate, error) { 92 k.cacheLock.Lock() 93 defer k.cacheLock.Unlock() 94 return k.certificate, nil 95 } 96 97 func (k *KeyLoader) Copy() *KeyLoader { 98 if k == nil { 99 return nil 100 } 101 102 new := KeyLoader{} 103 new.certificate = k.certificate 104 return &new 105 } 106 107 // GetKeyLoader returns the keyloader for a TLSConfig object. If the keyloader 108 // has not been initialized, it will first do so. 109 func (t *TLSConfig) GetKeyLoader() *KeyLoader { 110 t.keyloaderLock.Lock() 111 defer t.keyloaderLock.Unlock() 112 113 // If the keyloader has not yet been initialized, do it here 114 if t.KeyLoader == nil { 115 t.KeyLoader = &KeyLoader{} 116 } 117 return t.KeyLoader 118 } 119 120 // Copy copies the fields of TLSConfig to another TLSConfig object. Required as 121 // to not copy mutexes between objects. 122 func (t *TLSConfig) Copy() *TLSConfig { 123 if t == nil { 124 return t 125 } 126 127 new := &TLSConfig{} 128 new.EnableHTTP = t.EnableHTTP 129 new.EnableRPC = t.EnableRPC 130 new.VerifyServerHostname = t.VerifyServerHostname 131 new.CAFile = t.CAFile 132 new.CertFile = t.CertFile 133 134 t.keyloaderLock.Lock() 135 new.KeyLoader = t.KeyLoader.Copy() 136 t.keyloaderLock.Unlock() 137 138 new.KeyFile = t.KeyFile 139 new.RPCUpgradeMode = t.RPCUpgradeMode 140 new.VerifyHTTPSClient = t.VerifyHTTPSClient 141 return new 142 } 143 144 // Merge is used to merge two TLS configs together 145 func (t *TLSConfig) Merge(b *TLSConfig) *TLSConfig { 146 result := t.Copy() 147 148 if b.EnableHTTP { 149 result.EnableHTTP = true 150 } 151 if b.EnableRPC { 152 result.EnableRPC = true 153 } 154 if b.VerifyServerHostname { 155 result.VerifyServerHostname = true 156 } 157 if b.CAFile != "" { 158 result.CAFile = b.CAFile 159 } 160 if b.CertFile != "" { 161 result.CertFile = b.CertFile 162 } 163 if b.KeyFile != "" { 164 result.KeyFile = b.KeyFile 165 } 166 if b.VerifyHTTPSClient { 167 result.VerifyHTTPSClient = true 168 } 169 if b.RPCUpgradeMode { 170 result.RPCUpgradeMode = true 171 } 172 return result 173 }