Browse Source

Merge pull request #1244 from albertollamaso/reuse-aws-session

Once the AWS session is created first time, it can be reused
paul-the-alien[bot] 4 years ago
parent
commit
240b8db4f0
2 changed files with 56 additions and 8 deletions
  1. 6 0
      cmd/root.go
  2. 50 8
      pkg/provider/aws/auth/auth.go

+ 6 - 0
cmd/root.go

@@ -38,6 +38,7 @@ import (
 	"github.com/external-secrets/external-secrets/pkg/controllers/clusterexternalsecret"
 	"github.com/external-secrets/external-secrets/pkg/controllers/externalsecret"
 	"github.com/external-secrets/external-secrets/pkg/controllers/secretstore"
+	awsauth "github.com/external-secrets/external-secrets/pkg/provider/aws/auth"
 )
 
 var (
@@ -61,6 +62,7 @@ var (
 	secretName, secretNamespace           string
 	crdRequeueInterval                    time.Duration
 	certCheckInterval                     time.Duration
+	enableAWSSession                      bool
 )
 
 const (
@@ -159,6 +161,9 @@ var rootCmd = &cobra.Command{
 				os.Exit(1)
 			}
 		}
+		if enableAWSSession {
+			awsauth.EnableCache = true
+		}
 		setupLog.Info("starting manager")
 		if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
 			setupLog.Error(err, "problem running manager")
@@ -185,4 +190,5 @@ func init() {
 	rootCmd.Flags().BoolVar(&enableClusterExternalSecretReconciler, "enable-cluster-external-secret-reconciler", true, "Enable cluster external secret reconciler.")
 	rootCmd.Flags().DurationVar(&storeRequeueInterval, "store-requeue-interval", time.Minute*5, "Default Time duration between reconciling (Cluster)SecretStores")
 	rootCmd.Flags().BoolVar(&enableFloodGate, "enable-flood-gate", true, "Enable flood gate. External secret will be reconciled only if the ClusterStore or Store have an healthy or unknown state.")
+	rootCmd.Flags().BoolVar(&enableAWSSession, "experimental-enable-aws-session-cache", false, "Enable experimental AWS session cache. External secret will reuse the AWS session without creating a new one on each request.")
 }

+ 50 - 8
pkg/provider/aws/auth/auth.go

@@ -44,7 +44,18 @@ type Config struct {
 	APIRetries int
 }
 
-var log = ctrl.Log.WithName("provider").WithName("aws")
+type SessionCache struct {
+	Name            string
+	Namespace       string
+	Kind            string
+	ResourceVersion string
+}
+
+var (
+	log         = ctrl.Log.WithName("provider").WithName("aws")
+	sessions    = make(map[SessionCache]*session.Session)
+	EnableCache bool
+)
 
 const (
 	roleARNAnnotation = "eks.amazonaws.com/role-arn"
@@ -95,16 +106,12 @@ func New(ctx context.Context, store esv1beta1.GenericStore, kube client.Client,
 	if prov.Region != "" {
 		config.WithRegion(prov.Region)
 	}
-	handlers := defaults.Handlers()
-	handlers.Build.PushBack(request.WithAppendUserAgent("external-secrets"))
-	sess, err := session.NewSessionWithOptions(session.Options{
-		Config:            *config,
-		Handlers:          handlers,
-		SharedConfigState: session.SharedConfigDisable,
-	})
+
+	sess, err := getAWSSession(config, store, namespace)
 	if err != nil {
 		return nil, err
 	}
+
 	if prov.Role != "" {
 		stsclient := assumeRoler(sess)
 		sess.Config.WithCredentials(stscreds.NewCredentialsWithClient(stsclient, prov.Role))
@@ -232,3 +239,38 @@ type STSProvider func(*session.Session) stsiface.STSAPI
 func DefaultSTSProvider(sess *session.Session) stsiface.STSAPI {
 	return sts.New(sess)
 }
+
+// getAWSSession check if an AWS session should be reused
+// it returns the aws session or an error.
+func getAWSSession(config *aws.Config, store esv1beta1.GenericStore, namespace string) (*session.Session, error) {
+	tmpSession := SessionCache{
+		Name:            store.GetObjectMeta().Name,
+		Namespace:       namespace,
+		Kind:            store.GetTypeMeta().Kind,
+		ResourceVersion: store.GetObjectMeta().ResourceVersion,
+	}
+
+	if EnableCache {
+		sess, ok := sessions[tmpSession]
+		if ok {
+			log.Info("reusing aws session", "SecretStore", tmpSession.Name, "namespace", tmpSession.Namespace, "kind", tmpSession.Kind, "resourceversion", tmpSession.ResourceVersion)
+			return sess, nil
+		}
+	}
+
+	handlers := defaults.Handlers()
+	handlers.Build.PushBack(request.WithAppendUserAgent("external-secrets"))
+	sess, err := session.NewSessionWithOptions(session.Options{
+		Config:            *config,
+		Handlers:          handlers,
+		SharedConfigState: session.SharedConfigDisable,
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	if EnableCache {
+		sessions[tmpSession] = sess
+	}
+	return sess, nil
+}