Skip to content

Commit

Permalink
https enabled (#150)
Browse files Browse the repository at this point in the history
https enabled
  • Loading branch information
kpacha committed Sep 27, 2018
1 parent 4479755 commit 6e4ac44
Show file tree
Hide file tree
Showing 7 changed files with 489 additions and 67 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
vendor
server.rsa.crt
server.rsa.key
*.pem
*.json
*.yml
*.toml
*.dot
coverage.out
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ deps:
@echo ""

test:
go generate ./...
go test -cover -race ./...

benchmark:
Expand Down
16 changes: 16 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ type ServiceConfig struct {
// Plugin defines the configuration for the plugin loader
Plugin *Plugin `mapstructure:"plugin"`

// TLS defines the configuration params for enabling TLS (HTTPS & HTTP/2) at
// the router layer
TLS *TLS `mapstructure:"tls"`

// run krakend in debug mode
Debug bool
uriParser URIParser
Expand Down Expand Up @@ -217,6 +221,18 @@ type Plugin struct {
Pattern string `mapstructure:"pattern"`
}

// TLS defines the configuration params for enabling TLS (HTTPS & HTTP/2) at the router layer
type TLS struct {
IsDisabled bool `mapstructure:"disabled"`
PublicKey string `mapstructure:"public_key"`
PrivateKey string `mapstructure:"private_key"`
MinVersion string `mapstructure:"min_version"`
MaxVersion string `mapstructure:"max_version"`
CurvePreferences []uint16 `mapstructure:"curve_preferences"`
PreferServerCipherSuites bool `mapstructure:"prefer_server_cipher_suites"`
CipherSuites []uint16 `mapstructure:"cipher_suites"`
}

// ExtraConfig is a type to store extra configurations for customized behaviours
type ExtraConfig map[string]interface{}

Expand Down
10 changes: 6 additions & 4 deletions config/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ type parseableServiceConfig struct {
DialerFallbackDelay string `json:"dialer_fallback_delay"`
DialerKeepAlive string `json:"dialer_keep_alive"`
Debug bool
Plugin *Plugin
Plugin *Plugin `json:"plugin,omitempty"`
TLS *TLS `json:"tls,omitempty"`
}

func (p *parseableServiceConfig) normalize() ServiceConfig {
Expand Down Expand Up @@ -96,6 +97,7 @@ func (p *parseableServiceConfig) normalize() ServiceConfig {
DialerKeepAlive: parseDuration(p.DialerKeepAlive),
OutputEncoding: p.OutputEncoding,
Plugin: p.Plugin,
TLS: p.TLS,
}
if p.ExtraConfig != nil {
cfg.ExtraConfig = *p.ExtraConfig
Expand Down Expand Up @@ -161,9 +163,9 @@ type parseableBackend struct {

func (p *parseableBackend) normalize() *Backend {
b := Backend{
Group: p.Group,
Method: p.Method,
Host: p.Host,
Group: p.Group,
Method: p.Method,
Host: p.Host,
HostSanitizationDisabled: p.HostSanitizationDisabled,
URLPattern: p.URLPattern,
Blacklist: p.Blacklist,
Expand Down
179 changes: 179 additions & 0 deletions router/http/router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
package http

import (
"context"
"crypto/tls"
"errors"
"fmt"
"net"
"net/http"
"sync"
"time"

"github.com/devopsfaith/krakend/config"
"github.com/devopsfaith/krakend/core"
)

// ToHTTPError translates an error into a HTTP status code
type ToHTTPError func(error) int

// DefaultToHTTPError is a ToHTTPError transalator that always returns an
// internal server error
func DefaultToHTTPError(_ error) int {
return http.StatusInternalServerError
}

const (
HeaderCompleteResponseValue = "true"
HeaderIncompleteResponseValue = "false"
)

var (
// CompleteResponseHeaderName is the header to flag incomplete responses to the client
CompleteResponseHeaderName = "X-KrakenD-Completed"
// HeadersToSend are the headers to pass from the router request to the proxy
HeadersToSend = []string{"Content-Type"}
// UserAgentHeaderValue is the value of the User-Agent header to add to the proxy request
UserAgentHeaderValue = []string{core.KrakendUserAgent}

// ErrInternalError is the error returned by the router when something went wrong
ErrInternalError = errors.New("internal server error")
// ErrPrivateKey is the error returned by the router when the private key is not defined
ErrPrivateKey = errors.New("private key not defined")
// ErrPublicKey is the error returned by the router when the public key is not defined
ErrPublicKey = errors.New("public key not defined")
)

// InitHTTPDefaultTransport ensures the default HTTP transport is configured just once per execution
func InitHTTPDefaultTransport(cfg config.ServiceConfig) {
onceTransportConfig.Do(func() {
http.DefaultTransport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: cfg.DialerTimeout,
KeepAlive: cfg.DialerKeepAlive,
FallbackDelay: cfg.DialerFallbackDelay,
DualStack: true,
}).DialContext,
DisableCompression: cfg.DisableCompression,
DisableKeepAlives: cfg.DisableKeepAlives,
MaxIdleConns: cfg.MaxIdleConns,
MaxIdleConnsPerHost: cfg.MaxIdleConnsPerHost,
IdleConnTimeout: cfg.IdleConnTimeout,
ResponseHeaderTimeout: cfg.ResponseHeaderTimeout,
ExpectContinueTimeout: cfg.ExpectContinueTimeout,
TLSHandshakeTimeout: 10 * time.Second,
}
})
}

// RunServer runs a http.Server with the given handler and configuration.
// It configures the TLS layer if required by the received configuration.
func RunServer(ctx context.Context, cfg config.ServiceConfig, handler http.Handler) error {
done := make(chan error)
s := &http.Server{
Addr: fmt.Sprintf(":%d", cfg.Port),
Handler: handler,
ReadTimeout: cfg.ReadTimeout,
WriteTimeout: cfg.WriteTimeout,
ReadHeaderTimeout: cfg.ReadHeaderTimeout,
IdleTimeout: cfg.IdleTimeout,
TLSConfig: parseTLSConfig(cfg.TLS),
}

if s.TLSConfig == nil {
go func() {
done <- s.ListenAndServe()
}()
} else {
if cfg.TLS.PublicKey == "" {
return ErrPublicKey
}
if cfg.TLS.PrivateKey == "" {
return ErrPrivateKey
}
go func() {
done <- s.ListenAndServeTLS(cfg.TLS.PublicKey, cfg.TLS.PrivateKey)
}()
}

select {
case err := <-done:
return err
case <-ctx.Done():
return s.Shutdown(context.Background())
}
}

func parseTLSConfig(cfg *config.TLS) *tls.Config {
if cfg == nil {
return nil
}
if cfg.IsDisabled {
return nil
}

return &tls.Config{
MinVersion: parseTLSVersion(cfg.MinVersion),
MaxVersion: parseTLSVersion(cfg.MaxVersion),
CurvePreferences: parseCurveIDs(cfg),
PreferServerCipherSuites: cfg.PreferServerCipherSuites,
CipherSuites: parseCipherSuites(cfg),
}
}

func parseTLSVersion(key string) uint16 {
if v, ok := versions[key]; ok {
return v
}
return tls.VersionTLS12
}

func parseCurveIDs(cfg *config.TLS) []tls.CurveID {
l := len(cfg.CurvePreferences)
if l == 0 {
return defaultCurves
}

curves := make([]tls.CurveID, len(cfg.CurvePreferences))
for i := range curves {
curves[i] = tls.CurveID(cfg.CurvePreferences[i])
}
return curves
}

func parseCipherSuites(cfg *config.TLS) []uint16 {
l := len(cfg.CipherSuites)
if l == 0 {
return defaultCipherSuites
}

cs := make([]uint16, l)
for i := range cs {
cs[i] = uint16(cfg.CipherSuites[i])
}
return cs
}

var (
onceTransportConfig sync.Once
defaultCurves = []tls.CurveID{
tls.CurveP521,
tls.CurveP384,
tls.CurveP256,
}
defaultCipherSuites = []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
}
versions = map[string]uint16{
"SSL3.0": tls.VersionSSL30,
"TLS10": tls.VersionTLS10,
"TLS11": tls.VersionTLS11,
"TLS12": tls.VersionTLS12,
}
)
Loading

0 comments on commit 6e4ac44

Please sign in to comment.