mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-06 14:20:55 +03:00
add a new configuration section for HTTP clients
HTTP clients are used for executing hooks such as the ones used for custom actions, external authentication and pre-login user modifications. This allows, for example, to use self-signed certificate without defeating the purpose of using TLS
This commit is contained in:
86
httpclient/httpclient.go
Normal file
86
httpclient/httpclient.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package httpclient
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/drakkan/sftpgo/logger"
|
||||
"github.com/drakkan/sftpgo/utils"
|
||||
)
|
||||
|
||||
// Config defines the configuration for HTTP clients.
|
||||
// HTTP clients are used for executing hooks such as the ones used for
|
||||
// custom actions, external authentication and pre-login user modifications
|
||||
type Config struct {
|
||||
// Timeout specifies a time limit, in seconds, for requests
|
||||
Timeout int64 `json:"timeout" mapstructure:"timeout"`
|
||||
// CACertificates defines extra CA certificates to trust.
|
||||
// The paths can be absolute or relative to the config dir.
|
||||
// Adding trusted CA certificates is a convenient way to use self-signed
|
||||
// certificates without defeating the purpose of using TLS
|
||||
CACertificates []string `json:"ca_certificates" mapstructure:"ca_certificates"`
|
||||
customTransport *http.Transport
|
||||
}
|
||||
|
||||
const logSender = "httpclient"
|
||||
|
||||
var httpConfig Config
|
||||
|
||||
// Initialize configures HTTP clients
|
||||
func (c Config) Initialize(configDir string) {
|
||||
httpConfig = c
|
||||
rootCAs := c.loadCACerts(configDir)
|
||||
customTransport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
if customTransport.TLSClientConfig != nil {
|
||||
customTransport.TLSClientConfig.RootCAs = rootCAs
|
||||
} else {
|
||||
customTransport.TLSClientConfig = &tls.Config{
|
||||
RootCAs: rootCAs,
|
||||
}
|
||||
}
|
||||
httpConfig.customTransport = customTransport
|
||||
}
|
||||
|
||||
// loadCACerts returns system cert pools and try to add the configured
|
||||
// CA certificates to it
|
||||
func (c Config) loadCACerts(configDir string) *x509.CertPool {
|
||||
rootCAs, err := x509.SystemCertPool()
|
||||
if err != nil {
|
||||
rootCAs = x509.NewCertPool()
|
||||
}
|
||||
|
||||
for _, ca := range c.CACertificates {
|
||||
if !utils.IsFileInputValid(ca) {
|
||||
logger.Warn(logSender, "", "unable to load invalid CA certificate: %#v", ca)
|
||||
logger.WarnToConsole("unable to load invalid CA certificate: %#v", ca)
|
||||
continue
|
||||
}
|
||||
if !filepath.IsAbs(ca) {
|
||||
ca = filepath.Join(configDir, ca)
|
||||
}
|
||||
certs, err := ioutil.ReadFile(ca)
|
||||
if err != nil {
|
||||
logger.Warn(logSender, "", "unable to load CA certificate: %v", err)
|
||||
logger.WarnToConsole("unable to load CA certificate: %#v", err)
|
||||
}
|
||||
if rootCAs.AppendCertsFromPEM(certs) {
|
||||
logger.Debug(logSender, "", "CA certificate %#v added to the trusted certificates", ca)
|
||||
} else {
|
||||
logger.Warn(logSender, "", "unable to add CA certificate %#v to the trusted cetificates", ca)
|
||||
logger.WarnToConsole("unable to add CA certificate %#v to the trusted cetificates", ca)
|
||||
}
|
||||
}
|
||||
return rootCAs
|
||||
}
|
||||
|
||||
// GetHTTPClient returns an HTTP client with the configured parameters
|
||||
func GetHTTPClient() *http.Client {
|
||||
return &http.Client{
|
||||
Timeout: time.Duration(httpConfig.Timeout) * time.Second,
|
||||
Transport: httpConfig.customTransport,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user