Skip to content

Commit

Permalink
Reuse TLS config to avoid FD exhaustion (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
patricksanders authored Mar 19, 2021
1 parent 117191d commit 04a83d5
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 37 deletions.
7 changes: 5 additions & 2 deletions cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ import (
"strings"
"sync"

"github.com/netflix/weep/logging"

"github.com/netflix/weep/creds"
"github.com/netflix/weep/errors"
log "github.com/sirupsen/logrus"
"github.com/sirupsen/logrus"
)

var GlobalCache CredentialCache
var log = logging.GetLogger()

type CredentialCache struct {
sync.RWMutex
Expand All @@ -46,7 +49,7 @@ func getCacheSlug(role string, assume []string) string {
}

func (cc *CredentialCache) Get(role string, assumeChain []string) (*creds.RefreshableProvider, error) {
log.WithFields(log.Fields{
log.WithFields(logrus.Fields{
"role": role,
"assumeChain": assumeChain,
}).Info("retrieving credentials")
Expand Down
4 changes: 2 additions & 2 deletions cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import (
)

func init() {
serveCmd.PersistentFlags().StringVarP(&listenAddr, "listen-address", "a", "127.0.0.1", "IP address for the ECS credential provider to listen on")
serveCmd.PersistentFlags().IntVarP(&listenPort, "port", "p", viper.GetInt("server.ecs_credential_provider_port"), "port for the ECS credential provider service to listen on")
serveCmd.PersistentFlags().StringVarP(&listenAddr, "listen-address", "a", viper.GetString("server.address"), "IP address for the ECS credential provider to listen on")
serveCmd.PersistentFlags().IntVarP(&listenPort, "port", "p", viper.GetInt("server.port"), "port for the ECS credential provider service to listen on")
rootCmd.AddCommand(serveCmd)
}

Expand Down
13 changes: 11 additions & 2 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,19 @@ var log = logging.GetLogger()
func init() {
// Set default configuration values here
viper.SetTypeByDefaultValue(true)
viper.SetDefault("authentication_method", "challenge")
viper.SetDefault("aws.region", "us-east-1")
viper.SetDefault("feature_flags.consoleme_metadata", false)
viper.SetDefault("log_file", getDefaultLogFile())
viper.SetDefault("mtls_settings.old_cert_message", "mTLS certificate is too old, please refresh mtls certificate")
viper.SetDefault("server.http_timeout", 20)
viper.SetDefault("server.metadata_port", 9090)
viper.SetDefault("server.ecs_credential_provider_port", 9091)
viper.SetDefault("server.address", "127.0.0.1")
viper.SetDefault("server.port", 9091)
viper.SetDefault("service.command", "ecs_credential_provider")
viper.SetDefault("service.args", []string{})

// Set aliases for backward-compatibility
viper.RegisterAlias("server.ecs_credential_provider_port", "server.port")
}

func getDefaultLogFile() string {
Expand Down Expand Up @@ -149,6 +153,11 @@ func SetUser(user string) error {
return nil
}

func MtlsEnabled() bool {
authMethod := viper.GetString("authentication_method")
return authMethod == "mtls"
}

var (
Config WeepConfig
)
Expand Down
34 changes: 10 additions & 24 deletions creds/refreshable.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package creds

import (
"fmt"
"time"

"github.com/spf13/viper"
Expand All @@ -35,8 +36,6 @@ func NewRefreshableProvider(client HTTPClient, role, region string, assumeChain
NoIpRestrict: noIpRestrict,
AssumeChain: assumeChain,
client: client,
retries: 5,
retryDelay: 5,
}
err := rp.refresh()
if err != nil {
Expand All @@ -54,7 +53,6 @@ func (rp *RefreshableProvider) AutoRefresh() {
for {
select {
case _ = <-ticker.C:
log.Debugf("checking credentials for %s", rp.Role)
_, err := rp.checkAndRefresh(10)
if err != nil {
log.Error(err.Error())
Expand All @@ -81,34 +79,22 @@ func (rp *RefreshableProvider) refresh() error {
log.Debugf("refreshing credentials for %s", rp.Role)
var err error
var newCreds *AwsCredentials
retryDelay := time.Duration(rp.retryDelay) * time.Second

rp.Lock()
defer rp.Unlock()

RetryLoop:
for i := 0; i < rp.retries; i++ {
newCreds, err = GetCredentialsC(rp.client, rp.Role, rp.NoIpRestrict, rp.AssumeChain)
switch err {
case nil:
// Everything is happy, so we don't need to retry
break RetryLoop
case errors.MutualTLSCertNeedsRefreshError:
log.Error(viper.GetString("mtls_settings.old_cert_message"))
// Only prep for the next request and sleep if we have remaining retries
if i != rp.retries-1 {
// The http.Client, with the best of intentions, will hold the connection open,
// meaning that an auto-updated cert won't be used by the client.
rp.client.CloseIdleConnections()
time.Sleep(retryDelay)
}
default:
newCreds, err = GetCredentialsC(rp.client, rp.Role, rp.NoIpRestrict, rp.AssumeChain)
if err != nil {
if err == errors.MutualTLSCertNeedsRefreshError {
log.Error(err)
// The http.Client, with the best of intentions, will hold the connection open,
// meaning that an auto-updated cert won't be used by the client.
rp.client.CloseIdleConnections()
return fmt.Errorf(viper.GetString("mtls_settings.old_cert_message"))
} else {
return err
}
}
if err != nil {
return err
}

rp.Expiration = newCreds.Expiration
rp.value.AccessKeyID = newCreds.AccessKeyId
Expand Down
4 changes: 2 additions & 2 deletions example-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ aws:
region: us-east-1
server:
http_timeout: 20
metadata_port: 9090
ecs_credential_provider_port: 9091
address: 127.0.0.1
port: 9091
service:
command: ecs_credential_provider
args:
Expand Down
17 changes: 16 additions & 1 deletion httpAuth/mtls/mtls.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,23 @@ import (

var log = logging.GetLogger()

var tlsConfig *tls.Config

func init() {
if config.MtlsEnabled() {
var err error
tlsConfig, err = getTLSConfig()
if err != nil {
log.Fatalf("could not initialize mtls: %v", err)
}
}
}

// getTLSConfig makes and returns a pointer to a tls.Config
func getTLSConfig() (*tls.Config, error) {
if tlsConfig != nil {
return tlsConfig, nil
}
dirs, err := getTLSDirs()
if err != nil {
return nil, err
Expand All @@ -48,7 +63,7 @@ func getTLSConfig() (*tls.Config, error) {
if err != nil {
return nil, err
}
tlsConfig, err := makeTLSConfig(certFile, keyFile, caFile, insecure)
tlsConfig, err = makeTLSConfig(certFile, keyFile, caFile, insecure)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func Run(host string, port int, role, region string, shutdown chan os.Signal) er
router.HandleFunc("/{path:.*}", CredentialServiceMiddleware(CustomHandler))

go func() {
log.Info("Starting weep on ", listenAddr)
log.Info("starting weep on ", listenAddr)
srv := &http.Server{
ReadTimeout: 1 * time.Second,
WriteTimeout: 10 * time.Second,
Expand All @@ -64,6 +64,6 @@ func Run(host string, port int, role, region string, shutdown chan os.Signal) er

// Check for interrupt signal and exit cleanly
<-shutdown
log.Print("Shutdown signal received, stopping server...")
log.Print("shutdown signal received, stopping server...")
return nil
}
3 changes: 1 addition & 2 deletions weep-demo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ consoleme_url: https://demo.consolemeoss.com
mtls_settings:
old_cert_message: mTLS certificate is too old, please refresh mtls certificate
server:
ecs_credential_provider_port: 9091
port: 9091
http_timeout: 20
metadata_port: 9090

0 comments on commit 04a83d5

Please sign in to comment.