From 83359dce3fbe18f96482c8f3fcbe22660a033ccd Mon Sep 17 00:00:00 2001 From: Tim <32556895+Avarei@users.noreply.github.com> Date: Wed, 11 Sep 2024 22:23:22 +0200 Subject: [PATCH] add mtls Signed-off-by: Tim <32556895+Avarei@users.noreply.github.com> --- .../v1alpha2/disposablerequest_types.go | 3 + .../v1alpha2/zz_generated.deepcopy.go | 1 + apis/request/v1alpha2/request_types.go | 3 + .../request/v1alpha2/zz_generated.deepcopy.go | 1 + internal/clients/http/client.go | 61 +++++++++++++------ .../disposablerequest/disposablerequest.go | 21 ++++++- .../disposablerequest_test.go | 20 +++--- internal/controller/request/observe.go | 2 +- internal/controller/request/observe_test.go | 14 ++--- internal/controller/request/request.go | 22 ++++++- internal/controller/request/request_test.go | 18 +++--- .../requestgen/request_generator_test.go | 4 ++ internal/json/util_test.go | 4 ++ ...http.crossplane.io_disposablerequests.yaml | 14 +++++ package/crds/http.crossplane.io_requests.yaml | 14 +++++ 15 files changed, 152 insertions(+), 50 deletions(-) diff --git a/apis/disposablerequest/v1alpha2/disposablerequest_types.go b/apis/disposablerequest/v1alpha2/disposablerequest_types.go index ab6c5eb..72beda7 100644 --- a/apis/disposablerequest/v1alpha2/disposablerequest_types.go +++ b/apis/disposablerequest/v1alpha2/disposablerequest_types.go @@ -45,6 +45,9 @@ type DisposableRequestParameters struct { // InsecureSkipTLSVerify, when set to true, skips TLS certificate checks for the HTTP request InsecureSkipTLSVerify bool `json:"insecureSkipTLSVerify,omitempty"` + // TlsSecretRef expects a reference to an opaque secret containing tls.crt and tls.key or/and ca.crt + TlsSecretRef xpv1.SecretReference `json:"tlsSecretRef,omitempty"` + // ExpectedResponse is a jq filter expression used to evaluate the HTTP response and determine if it matches the expected criteria. // The expression should return a boolean; if true, the response is considered expected. // Example: '.body.job_status == "success"' diff --git a/apis/disposablerequest/v1alpha2/zz_generated.deepcopy.go b/apis/disposablerequest/v1alpha2/zz_generated.deepcopy.go index 7a363eb..9128574 100644 --- a/apis/disposablerequest/v1alpha2/zz_generated.deepcopy.go +++ b/apis/disposablerequest/v1alpha2/zz_generated.deepcopy.go @@ -113,6 +113,7 @@ func (in *DisposableRequestParameters) DeepCopyInto(out *DisposableRequestParame *out = new(int32) **out = **in } + out.TlsSecretRef = in.TlsSecretRef if in.NextReconcile != nil { in, out := &in.NextReconcile, &out.NextReconcile *out = new(v1.Duration) diff --git a/apis/request/v1alpha2/request_types.go b/apis/request/v1alpha2/request_types.go index b685c0f..a1aee4e 100644 --- a/apis/request/v1alpha2/request_types.go +++ b/apis/request/v1alpha2/request_types.go @@ -42,6 +42,9 @@ type RequestParameters struct { // InsecureSkipTLSVerify, when set to true, skips TLS certificate checks for the HTTP request InsecureSkipTLSVerify bool `json:"insecureSkipTLSVerify,omitempty"` + // TlsSecretRef expects a reference to an opaque secret containing tls.crt and tls.key or/and ca.crt + TlsSecretRef xpv1.SecretReference `json:"tlsSecretRef,omitempty"` + // SecretInjectionConfig specifies the secrets receiving patches for response data. SecretInjectionConfigs []SecretInjectionConfig `json:"secretInjectionConfigs,omitempty"` } diff --git a/apis/request/v1alpha2/zz_generated.deepcopy.go b/apis/request/v1alpha2/zz_generated.deepcopy.go index 6301c31..8ed214e 100644 --- a/apis/request/v1alpha2/zz_generated.deepcopy.go +++ b/apis/request/v1alpha2/zz_generated.deepcopy.go @@ -178,6 +178,7 @@ func (in *RequestParameters) DeepCopyInto(out *RequestParameters) { *out = new(v1.Duration) **out = **in } + out.TlsSecretRef = in.TlsSecretRef if in.SecretInjectionConfigs != nil { in, out := &in.SecretInjectionConfigs, &out.SecretInjectionConfigs *out = make([]SecretInjectionConfig, len(*in)) diff --git a/internal/clients/http/client.go b/internal/clients/http/client.go index b99d229..2126c79 100644 --- a/internal/clients/http/client.go +++ b/internal/clients/http/client.go @@ -4,7 +4,9 @@ import ( "bytes" "context" "crypto/tls" + "crypto/x509" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -15,12 +17,12 @@ import ( // Client is the interface to interact with Http type Client interface { - SendRequest(ctx context.Context, method string, url string, body Data, headers Data, skipTLSVerify bool) (resp HttpDetails, err error) + SendRequest(ctx context.Context, method string, url string, body Data, headers Data) (resp HttpDetails, err error) } type client struct { - log logging.Logger - timeout time.Duration + client http.Client + log logging.Logger } type HttpResponse struct { @@ -46,7 +48,7 @@ type HttpDetails struct { HttpRequest HttpRequest } -func (hc *client) SendRequest(ctx context.Context, method string, url string, body Data, headers Data, skipTLSVerify bool) (details HttpDetails, err error) { +func (hc *client) SendRequest(ctx context.Context, method string, url string, body Data, headers Data) (details HttpDetails, err error) { requestBody := []byte(body.Decrypted.(string)) request, err := http.NewRequestWithContext(ctx, method, url, bytes.NewBuffer(requestBody)) requestDetails := HttpRequest{ @@ -68,16 +70,7 @@ func (hc *client) SendRequest(ctx context.Context, method string, url string, bo } } - client := &http.Client{ - Transport: &http.Transport{ - // #nosec G402 - TLSClientConfig: &tls.Config{InsecureSkipVerify: skipTLSVerify}, - Proxy: http.ProxyFromEnvironment, // Use proxy settings from environment - }, - Timeout: hc.timeout, - } - - response, err := client.Do(request) + response, err := hc.client.Do(request) if err != nil { return HttpDetails{ HttpRequest: requestDetails, @@ -113,10 +106,21 @@ func (hc *client) SendRequest(ctx context.Context, method string, url string, bo } // NewClient returns a new Http Client -func NewClient(log logging.Logger, timeout time.Duration) (Client, error) { +func NewClient(log logging.Logger, timeout time.Duration, certPEMBlock, keyPEMBlock, caPEMBlock []byte, insecureSkipVerify bool) (Client, error) { + tlsConfig, err := tlsConfig(certPEMBlock, keyPEMBlock, caPEMBlock, insecureSkipVerify) + if err != nil { + return nil, err + } + httpClient := http.Client{ + Transport: &http.Transport{ + TLSClientConfig: tlsConfig, + Proxy: http.ProxyFromEnvironment, // Use proxy settings from environment + }, + Timeout: timeout, + } return &client{ - log: log, - timeout: timeout, + client: httpClient, + log: log, }, nil } @@ -128,3 +132,26 @@ func toJSON(request HttpRequest) string { return string(jsonBytes) } + +func tlsConfig(certPEMBlock, keyPEMBlock, caPEMBlock []byte, insecureSkipVerify bool) (*tls.Config, error) { + tlsConfig := &tls.Config{} + if len(certPEMBlock) > 0 && len(keyPEMBlock) > 0 { + certificate, err := tls.X509KeyPair(certPEMBlock, keyPEMBlock) + if err != nil { + return nil, err + } + tlsConfig.Certificates = []tls.Certificate{certificate} + } + + if len(caPEMBlock) > 0 { + caPool := x509.NewCertPool() + if !caPool.AppendCertsFromPEM(caPEMBlock) { + return nil, errors.New("some error appending the ca.crt") + } + tlsConfig.RootCAs = caPool + } + + tlsConfig.InsecureSkipVerify = insecureSkipVerify + + return tlsConfig, nil +} diff --git a/internal/controller/disposablerequest/disposablerequest.go b/internal/controller/disposablerequest/disposablerequest.go index 4a27a07..5887d16 100644 --- a/internal/controller/disposablerequest/disposablerequest.go +++ b/internal/controller/disposablerequest/disposablerequest.go @@ -42,6 +42,7 @@ import ( apisv1alpha1 "github.com/crossplane-contrib/provider-http/apis/v1alpha1" httpClient "github.com/crossplane-contrib/provider-http/internal/clients/http" "github.com/crossplane-contrib/provider-http/internal/utils" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -94,7 +95,7 @@ type connector struct { logger logging.Logger kube client.Client usage resource.Tracker - newHttpClientFn func(log logging.Logger, timeout time.Duration) (httpClient.Client, error) + newHttpClientFn func(log logging.Logger, timeout time.Duration, certPEMBlock, keyPEMBlock, caPEMBlock []byte, insecureSkipVerify bool) (httpClient.Client, error) } func (c *connector) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) { @@ -115,7 +116,21 @@ func (c *connector) Connect(ctx context.Context, mg resource.Managed) (managed.E return nil, errors.Wrap(err, errProviderNotRetrieved) } - h, err := c.newHttpClientFn(l, utils.WaitTimeout(cr.Spec.ForProvider.WaitTimeout)) + secret := &corev1.Secret{} + + if cr.Spec.ForProvider.TlsSecretRef.Name != "" && cr.Spec.ForProvider.TlsSecretRef.Namespace != "" { + if err := c.kube.Get(ctx, types.NamespacedName{ + Namespace: cr.Spec.ForProvider.TlsSecretRef.Namespace, + Name: cr.Spec.ForProvider.TlsSecretRef.Name, + }, secret); err != nil { + return nil, errors.Wrap(err, errGetReferencedSecret) + } + } + certPEMBlock := secret.Data["tls.crt"] + keyPEMBlock := secret.Data["tls.key"] + caPEMBlock := secret.Data["ca.crt"] + + h, err := c.newHttpClientFn(l, utils.WaitTimeout(cr.Spec.ForProvider.WaitTimeout), certPEMBlock, keyPEMBlock, caPEMBlock, cr.Spec.ForProvider.InsecureSkipTLSVerify) if err != nil { return nil, errors.Wrap(err, errNewHttpClient) } @@ -184,7 +199,7 @@ func (c *external) deployAction(ctx context.Context, cr *v1alpha2.DisposableRequ bodyData := httpClient.Data{Encrypted: cr.Spec.ForProvider.Body, Decrypted: sensitiveBody} headersData := httpClient.Data{Encrypted: cr.Spec.ForProvider.Headers, Decrypted: sensitiveHeaders} - details, err := c.http.SendRequest(ctx, cr.Spec.ForProvider.Method, cr.Spec.ForProvider.URL, bodyData, headersData, cr.Spec.ForProvider.InsecureSkipTLSVerify) + details, err := c.http.SendRequest(ctx, cr.Spec.ForProvider.Method, cr.Spec.ForProvider.URL, bodyData, headersData) sensitiveResponse := details.HttpResponse resource := &utils.RequestResource{ diff --git a/internal/controller/disposablerequest/disposablerequest_test.go b/internal/controller/disposablerequest/disposablerequest_test.go index eabd46b..c9b00c4 100644 --- a/internal/controller/disposablerequest/disposablerequest_test.go +++ b/internal/controller/disposablerequest/disposablerequest_test.go @@ -103,14 +103,14 @@ func httpDisposableRequest(rm ...httpDisposableRequestModifier) *v1alpha2.Dispos return r } -type MockSendRequestFn func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) +type MockSendRequestFn func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data) (resp httpClient.HttpDetails, err error) type MockHttpClient struct { MockSendRequest MockSendRequestFn } -func (c *MockHttpClient) SendRequest(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { - return c.MockSendRequest(ctx, method, url, body, headers, skipTLSVerify) +func (c *MockHttpClient) SendRequest(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { + return c.MockSendRequest(ctx, method, url, body, headers) } type notHttpDisposableRequest struct { @@ -143,7 +143,7 @@ func Test_httpExternal_Create(t *testing.T) { "DisposableRequestFailed": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{}, errBoom }, }, @@ -161,7 +161,7 @@ func Test_httpExternal_Create(t *testing.T) { "Success": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{}, nil }, }, @@ -219,7 +219,7 @@ func Test_httpExternal_Update(t *testing.T) { "DisposableRequestFailed": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{}, errBoom }, }, @@ -236,7 +236,7 @@ func Test_httpExternal_Update(t *testing.T) { "Success": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{}, nil }, }, @@ -290,7 +290,7 @@ func Test_deployAction(t *testing.T) { "SuccessUpdateStatusRequestFailure": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{}, errors.Errorf(utils.ErrInvalidURL, "invalid-url") }, }, @@ -318,7 +318,7 @@ func Test_deployAction(t *testing.T) { "SuccessUpdateStatusCodeError": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{ HttpResponse: httpClient.HttpResponse{ StatusCode: 400, @@ -356,7 +356,7 @@ func Test_deployAction(t *testing.T) { "SuccessUpdateStatusSuccessfulRequest": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{ HttpResponse: httpClient.HttpResponse{ StatusCode: 200, diff --git a/internal/controller/request/observe.go b/internal/controller/request/observe.go index b2d41b6..c3305b8 100644 --- a/internal/controller/request/observe.go +++ b/internal/controller/request/observe.go @@ -54,7 +54,7 @@ func (c *external) isUpToDate(ctx context.Context, cr *v1alpha2.Request) (Observ return FailedObserve(), err } - details, responseErr := c.http.SendRequest(ctx, http.MethodGet, requestDetails.Url, requestDetails.Body, requestDetails.Headers, cr.Spec.ForProvider.InsecureSkipTLSVerify) + details, responseErr := c.http.SendRequest(ctx, http.MethodGet, requestDetails.Url, requestDetails.Body, requestDetails.Headers) if details.HttpResponse.StatusCode == http.StatusNotFound { return FailedObserve(), errors.New(errObjectNotFound) } diff --git a/internal/controller/request/observe_test.go b/internal/controller/request/observe_test.go index add3044..d07a964 100644 --- a/internal/controller/request/observe_test.go +++ b/internal/controller/request/observe_test.go @@ -36,7 +36,7 @@ func Test_isUpToDate(t *testing.T) { "ObjectNotFoundEmptyBody": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{}, nil }, }, @@ -54,7 +54,7 @@ func Test_isUpToDate(t *testing.T) { "ObjectNotFoundPostFailed": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{}, nil }, }, @@ -73,7 +73,7 @@ func Test_isUpToDate(t *testing.T) { "ObjectNotFound404StatusCode": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{}, nil }, }, @@ -91,7 +91,7 @@ func Test_isUpToDate(t *testing.T) { "FailBodyNotJSON": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{ HttpResponse: httpClient.HttpResponse{ Body: "not a JSON", @@ -113,7 +113,7 @@ func Test_isUpToDate(t *testing.T) { "SuccessNotSynced": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{ HttpResponse: httpClient.HttpResponse{ Body: `{"username":"old_name"}`, @@ -147,7 +147,7 @@ func Test_isUpToDate(t *testing.T) { "SuccessNoPUTMapping": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{ HttpResponse: httpClient.HttpResponse{ Body: `{"username":"old_name"}`, @@ -187,7 +187,7 @@ func Test_isUpToDate(t *testing.T) { "SuccessJSONBody": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{ HttpResponse: httpClient.HttpResponse{ Body: `{"username":"john_doe_new_username"}`, diff --git a/internal/controller/request/request.go b/internal/controller/request/request.go index 369a1e0..55b8e99 100644 --- a/internal/controller/request/request.go +++ b/internal/controller/request/request.go @@ -42,6 +42,7 @@ import ( "github.com/crossplane-contrib/provider-http/internal/controller/request/statushandler" datapatcher "github.com/crossplane-contrib/provider-http/internal/data-patcher" "github.com/crossplane-contrib/provider-http/internal/utils" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -57,6 +58,7 @@ const ( errMappingNotFound = "%s mapping doesn't exist in request, skipping operation" errPatchDataToSecret = "Warning, couldn't patch data from request to secret %s:%s:%s, error: %s" errGetLatestVersion = "failed to get the latest version of the resource" + errGetReferencedSecret = "cannot get referenced secret" ) // Setup adds a controller that reconciles Request managed resources. @@ -92,7 +94,7 @@ type connector struct { logger logging.Logger kube client.Client usage resource.Tracker - newHttpClientFn func(log logging.Logger, timeout time.Duration) (httpClient.Client, error) + newHttpClientFn func(log logging.Logger, timeout time.Duration, certPEMBlock, keyPEMBlock, caPEMBlock []byte, insecureSkipVerify bool) (httpClient.Client, error) } // Connect typically produces an ExternalClient by: @@ -118,7 +120,21 @@ func (c *connector) Connect(ctx context.Context, mg resource.Managed) (managed.E return nil, errors.Wrap(err, errProviderNotRetrieved) } - h, err := c.newHttpClientFn(l, utils.WaitTimeout(cr.Spec.ForProvider.WaitTimeout)) + secret := &corev1.Secret{} + + if cr.Spec.ForProvider.TlsSecretRef.Name != "" && cr.Spec.ForProvider.TlsSecretRef.Namespace != "" { + if err := c.kube.Get(ctx, types.NamespacedName{ + Namespace: cr.Spec.ForProvider.TlsSecretRef.Namespace, + Name: cr.Spec.ForProvider.TlsSecretRef.Name, + }, secret); err != nil { + return nil, errors.Wrap(err, errGetReferencedSecret) + } + } + certPEMBlock := secret.Data["tls.crt"] + keyPEMBlock := secret.Data["tls.key"] + caPEMBlock := secret.Data["ca.crt"] + + h, err := c.newHttpClientFn(l, utils.WaitTimeout(cr.Spec.ForProvider.WaitTimeout), certPEMBlock, keyPEMBlock, caPEMBlock, cr.Spec.ForProvider.InsecureSkipTLSVerify) if err != nil { return nil, errors.Wrap(err, errNewHttpClient) } @@ -195,7 +211,7 @@ func (c *external) deployAction(ctx context.Context, cr *v1alpha2.Request, metho return err } - details, err := c.http.SendRequest(ctx, mapping.Method, requestDetails.Url, requestDetails.Body, requestDetails.Headers, cr.Spec.ForProvider.InsecureSkipTLSVerify) + details, err := c.http.SendRequest(ctx, mapping.Method, requestDetails.Url, requestDetails.Body, requestDetails.Headers) c.patchResponseToSecret(ctx, cr, &details.HttpResponse) statusHandler, err := statushandler.NewStatusHandler(ctx, cr, details, err, c.localKube, c.logger) diff --git a/internal/controller/request/request_test.go b/internal/controller/request/request_test.go index cae539d..01350e4 100644 --- a/internal/controller/request/request_test.go +++ b/internal/controller/request/request_test.go @@ -72,14 +72,14 @@ type notHttpRequest struct { resource.Managed } -type MockSendRequestFn func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) +type MockSendRequestFn func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data) (resp httpClient.HttpDetails, err error) type MockHttpClient struct { MockSendRequest MockSendRequestFn } -func (c *MockHttpClient) SendRequest(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { - return c.MockSendRequest(ctx, method, url, body, headers, skipTLSVerify) +func (c *MockHttpClient) SendRequest(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { + return c.MockSendRequest(ctx, method, url, body, headers) } type MockSetRequestStatusFn func() error @@ -126,7 +126,7 @@ func Test_httpExternal_Create(t *testing.T) { "RequestFailed": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{}, errBoom }, }, @@ -143,7 +143,7 @@ func Test_httpExternal_Create(t *testing.T) { "Success": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{}, nil }, }, @@ -201,7 +201,7 @@ func Test_httpExternal_Update(t *testing.T) { "RequestFailed": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{}, errBoom }, }, @@ -218,7 +218,7 @@ func Test_httpExternal_Update(t *testing.T) { "Success": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{}, nil }, }, @@ -276,7 +276,7 @@ func Test_httpExternal_Delete(t *testing.T) { "RequestFailed": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{}, errBoom }, }, @@ -293,7 +293,7 @@ func Test_httpExternal_Delete(t *testing.T) { "Success": { args: args{ http: &MockHttpClient{ - MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data, skipTLSVerify bool) (resp httpClient.HttpDetails, err error) { + MockSendRequest: func(ctx context.Context, method string, url string, body httpClient.Data, headers httpClient.Data) (resp httpClient.HttpDetails, err error) { return httpClient.HttpDetails{}, nil }, }, diff --git a/internal/controller/request/requestgen/request_generator_test.go b/internal/controller/request/requestgen/request_generator_test.go index 3947ae1..28d1f04 100644 --- a/internal/controller/request/requestgen/request_generator_test.go +++ b/internal/controller/request/requestgen/request_generator_test.go @@ -424,6 +424,10 @@ func Test_generateRequestObject(t *testing.T) { "body": map[string]any{"id": "123"}, "statusCode": float64(200), }, + "tlsSecretRef": map[string]any{ + "name": "", + "namespace": "", + }, }, }, }, diff --git a/internal/json/util_test.go b/internal/json/util_test.go index ed3c698..a52a7e1 100644 --- a/internal/json/util_test.go +++ b/internal/json/util_test.go @@ -293,6 +293,10 @@ func Test_StructToMap(t *testing.T) { "baseUrl": "https://api.example.com/users", "body": `{"username": "john_doe", "email": "john.doe@example.com"}`, }, + "tlsSecretRef": map[string]any{ + "name": "", + "namespace": "", + }, }, errMessage: "", }, diff --git a/package/crds/http.crossplane.io_disposablerequests.yaml b/package/crds/http.crossplane.io_disposablerequests.yaml index 8ac26a5..eaa1d1b 100644 --- a/package/crds/http.crossplane.io_disposablerequests.yaml +++ b/package/crds/http.crossplane.io_disposablerequests.yaml @@ -528,6 +528,20 @@ spec: description: ShouldLoopInfinitely specifies whether the reconciliation should loop indefinitely. type: boolean + tlsSecretRef: + description: TlsSecretRef expects a reference to an opaque secret + containing tls.crt and tls.key or/and ca.crt + properties: + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - name + - namespace + type: object url: type: string x-kubernetes-validations: diff --git a/package/crds/http.crossplane.io_requests.yaml b/package/crds/http.crossplane.io_requests.yaml index ef57d72..05648a9 100644 --- a/package/crds/http.crossplane.io_requests.yaml +++ b/package/crds/http.crossplane.io_requests.yaml @@ -556,6 +556,20 @@ spec: - secretRef type: object type: array + tlsSecretRef: + description: TlsSecretRef expects a reference to an opaque secret + containing tls.crt and tls.key or/and ca.crt + properties: + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - name + - namespace + type: object waitTimeout: description: WaitTimeout specifies the maximum time duration for waiting.