Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions fleetspeak/src/client/comms.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ func (c commsContext) ServerInfo() (comms.ServerInfo, error) {
Servers: cfg.Servers,
Proxy: cfg.Proxy,
ClientCertificateHeader: cfg.ClientCertificateHeader,
GetAuthCertificate: cfg.GetAuthCertificate,
ServerName: cfg.ServerName,
}, nil
}
Expand Down
11 changes: 8 additions & 3 deletions fleetspeak/src/client/comms/comms.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package comms
import (
"context"
"crypto"
"crypto/tls"
"crypto/x509"
"io"
"net/url"
Expand Down Expand Up @@ -74,14 +75,18 @@ type ServerInfo struct {
// attempt to communicate with.
Servers []string

// If non-nil, proxy used for connecting to the server.
// If set, proxy used for connecting to the server.
// See https://golang.org/pkg/net/http/#Transport.Proxy for details.
Proxy *url.URL

// If non-empty, populated with the header to use for the
// client certificate header
// If set, the communicator must include the client certificate in this header
// in all requests to the server.
ClientCertificateHeader string

// If set, the communicator must use the certificate provided by this function
// for authentication, instead of the client certificate.
GetAuthCertificate func(*tls.CertificateRequestInfo) (*tls.Certificate, error)

// If set, used for SNI and certificate validation.
ServerName string
}
Expand Down
20 changes: 17 additions & 3 deletions fleetspeak/src/client/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package config

import (
"crypto/tls"
"crypto/x509"
"net/url"

Expand Down Expand Up @@ -78,10 +79,23 @@ type Configuration struct {
// See https://golang.org/pkg/net/http/#Transport.Proxy for details.
Proxy *url.URL

// If set, the server will validate the client certificate from the request header.
// This should be used if TLS is terminated at the load balancer and client certificates
// can be passed upstream to the fleetspeak server as an http header.
// If set, the communicator includes the client certificate in this header,
// which the server will use to identify the client. This should be used if
// TLS is terminated by e.g. a load balancer that can forward the certificate
// to the server as another header, so that the server can check the
// forwarded certificate against this header.
// If the proxy can not forward the certificate to the server, there is no
// guarantee that the certificate in this header is the actual client's
// certificate, making identity spoofing possible.
ClientCertificateHeader string

// If set, used instead of the client certificate for authenticating with a
// the server or a proxy. Requires ClientCertificateHeader to be set for the
// server to still be able to identify the client.
// Using this setting waives Fleetspeak's identity guarantees and offloads
// the identity verification to the system that provides and verifies the
// certificate.
GetAuthCertificate func(*tls.CertificateRequestInfo) (*tls.Certificate, error)
}

// PersistenceHandler manages client's configuration storage.
Expand Down
19 changes: 12 additions & 7 deletions fleetspeak/src/client/https/https.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,21 @@ func makeTransport(cctx comms.Context, dc func(ctx context.Context, network, add
nextProtos = []string{"h2", "http/1.1"}
}

getClientCert := si.GetAuthCertificate
if getClientCert == nil {
getClientCert = func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
return &tls.Certificate{
Certificate: [][]byte{certBytes},
PrivateKey: ci.Private,
}, nil
}
}

tr := &http.Transport{
Proxy: proxy,
TLSClientConfig: &tls.Config{
RootCAs: si.TrustedCerts,
GetClientCertificate: func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
return &tls.Certificate{
Certificate: [][]byte{certBytes},
PrivateKey: ci.Private,
}, nil
},
RootCAs: si.TrustedCerts,
GetClientCertificate: getClientCert,
CipherSuites: []uint16{
// We implement both endpoints, so we might as well require long keys and
// perfect forward secrecy. Note that TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Expand Down
Loading