github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/securehttp/caller.go (about)

     1  package securehttp
     2  
     3  import (
     4  	"net/http"
     5  	"time"
     6  
     7  	"github.com/kyma-incubator/compass/components/director/pkg/certloader"
     8  
     9  	"github.com/kyma-incubator/compass/components/director/pkg/oauth"
    10  
    11  	"github.com/pkg/errors"
    12  
    13  	"github.com/kyma-incubator/compass/components/director/pkg/auth"
    14  	director_http "github.com/kyma-incubator/compass/components/director/pkg/http"
    15  )
    16  
    17  // CallerConfig holds the configuration for Caller
    18  type CallerConfig struct {
    19  	Credentials   auth.Credentials
    20  	ClientTimeout time.Duration
    21  
    22  	SkipSSLValidation            bool
    23  	Cache                        certloader.Cache
    24  	ExternalClientCertSecretName string
    25  }
    26  
    27  // Caller can be used to call secured http endpoints with given credentials
    28  type Caller struct {
    29  	Credentials auth.Credentials
    30  
    31  	Provider director_http.AuthorizationProvider
    32  	client   *http.Client
    33  }
    34  
    35  // NewCaller creates a new Caller
    36  func NewCaller(config CallerConfig) (*Caller, error) {
    37  	c := &Caller{
    38  		Credentials: config.Credentials,
    39  		client:      &http.Client{Timeout: config.ClientTimeout},
    40  	}
    41  
    42  	switch config.Credentials.Type() {
    43  	case auth.BasicCredentialType:
    44  		c.Provider = auth.NewBasicAuthorizationProvider()
    45  	case auth.OAuthCredentialType:
    46  		c.Provider = auth.NewTokenAuthorizationProvider(&http.Client{Timeout: config.ClientTimeout})
    47  	case auth.OAuthMtlsCredentialType:
    48  		oauthCfg := oauth.Config{
    49  			TokenRequestTimeout: config.ClientTimeout,
    50  			SkipSSLValidation:   config.SkipSSLValidation,
    51  		}
    52  		credentials, ok := config.Credentials.Get().(*auth.OAuthMtlsCredentials)
    53  		if !ok {
    54  			return nil, errors.New("failed to cast credentials to mtls oauth credentials type")
    55  		}
    56  		c.Provider = auth.NewMtlsTokenAuthorizationProvider(oauthCfg, config.ExternalClientCertSecretName, credentials.CertCache, auth.DefaultMtlsClientCreator)
    57  	}
    58  	c.client.Transport = director_http.NewCorrelationIDTransport(director_http.NewSecuredTransport(director_http.NewHTTPTransportWrapper(http.DefaultTransport.(*http.Transport)), c.Provider))
    59  	return c, nil
    60  }
    61  
    62  // Call executes a http call with the configured credentials
    63  func (c *Caller) Call(req *http.Request) (*http.Response, error) {
    64  	req = c.addCredentialsToContext(req)
    65  	resp, err := c.client.Do(req)
    66  	if err != nil {
    67  		return nil, errors.Wrapf(err, "while executing call to %s: ", req.URL)
    68  	}
    69  	return resp, nil
    70  }
    71  
    72  func (c *Caller) addCredentialsToContext(req *http.Request) *http.Request {
    73  	authCtx := req.Context()
    74  	authCtx = auth.SaveToContext(authCtx, c.Credentials)
    75  	return req.WithContext(authCtx)
    76  }